Skip to content

Exception edges for live range analysis master #466

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/java_bytecode/java_bytecode_convert_method_class.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,8 @@ class java_bytecode_convert_methodt:public messaget

public:
typedef std::map<unsigned, converted_instructiont> address_mapt;
typedef cfg_dominators_templatet<const address_mapt, unsigned, false>
typedef std::pair<const methodt&, const address_mapt&> method_with_amapt;
typedef cfg_dominators_templatet<method_with_amapt, unsigned, false>
java_cfg_dominatorst;

protected:
Expand Down
6 changes: 5 additions & 1 deletion src/java_bytecode/java_bytecode_parse_tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,12 @@ class java_bytecode_parse_treet
return instructions.back();
}

class exceptiont
struct exceptiont
{
std::size_t start_pc;
std::size_t end_pc;
std::size_t handler_pc;
symbol_typet catch_type;
};

typedef std::vector<exceptiont> exception_tablet;
Expand Down
15 changes: 11 additions & 4 deletions src/java_bytecode/java_bytecode_parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -968,13 +968,20 @@ void java_bytecode_parsert::rmethod_attribute(methodt &method)
rbytecode(method.instructions);

u2 exception_table_length=read_u2();
method.exception_table.resize(exception_table_length);

for(std::size_t e=0; e<exception_table_length; e++)
{
u2 UNUSED start_pc=read_u2();
u2 UNUSED end_pc=read_u2();
u2 UNUSED handler_pc=read_u2();
u2 UNUSED catch_type=read_u2();
u2 start_pc=read_u2();
u2 end_pc=read_u2();
u2 handler_pc=read_u2();
u2 catch_type=read_u2();
method.exception_table[e].start_pc=start_pc;
method.exception_table[e].end_pc=end_pc;
method.exception_table[e].handler_pc=handler_pc;
if(catch_type!=0)
method.exception_table[e].catch_type=
to_symbol_type(pool_entry(catch_type).expr.type());
}

u2 attributes_count=read_u2();
Expand Down
115 changes: 72 additions & 43 deletions src/java_bytecode/java_local_variable_table.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,43 +20,71 @@ Author: Chris Smowton, [email protected]
template<class T>
struct procedure_local_cfg_baset<
T,
const java_bytecode_convert_methodt::address_mapt,
java_bytecode_convert_methodt::method_with_amapt,
unsigned> :
public graph<cfg_base_nodet<T, unsigned> >
{
typedef java_bytecode_convert_methodt::address_mapt address_mapt;
typedef java_bytecode_convert_methodt::method_with_amapt method_with_amapt;
typedef std::map<unsigned, unsigned> entry_mapt;
entry_mapt entry_map;

procedure_local_cfg_baset() {}

void operator()(const address_mapt& amap)
void operator()(const method_with_amapt &args)
{
for(const auto& inst : amap)
const auto &method=args.first;
const auto &amap=args.second;
for(const auto &inst : amap)
{
// Map instruction PCs onto node indices:
entry_map[inst.first]=this->add_node();
// Map back:
(*this)[entry_map[inst.first]].PC=inst.first;
}
for(const auto& inst : amap)
// Add edges declared in the address map:
for(const auto &inst : amap)
{
for(auto succ : inst.second.successors)
this->add_edge(entry_map.at(inst.first), entry_map.at(succ));
}
// Next, add edges declared in the exception table, which
// don't figure in the address map successors/predecessors as yet:
for(const auto &table_entry : method.exception_table)
{
auto findit=amap.find(table_entry.start_pc);
assert(findit!=amap.end() &&
"Exception table entry doesn't point to an instruction?");
for(; findit->first<table_entry.end_pc; ++findit)
{
// For now just assume any non-branch
// instruction could potentially throw.
auto succit=findit;
++succit;
if(succit==amap.end())
continue;
const auto &thisinst=findit->second;
if(thisinst.successors.size()==1 &&
thisinst.successors.back()==succit->first)
{
this->add_edge(
entry_map.at(findit->first),
entry_map.at(table_entry.handler_pc));
}
}
}
}

unsigned get_first_node(const address_mapt& amap) const
unsigned get_first_node(const method_with_amapt &args) const
{
return amap.begin()->first;
return args.second.begin()->first;
}
unsigned get_last_node(const address_mapt& amap) const
unsigned get_last_node(const method_with_amapt &args) const
{
return (--amap.end())->first;
return (--args.second.end())->first;
}
unsigned nodes_empty(const address_mapt& amap) const
unsigned nodes_empty(const method_with_amapt &args) const
{
return amap.empty();
return args.second.empty();
}
};

Expand All @@ -75,8 +103,8 @@ typedef java_bytecode_convert_methodt::java_cfg_dominatorst
// Comparators for local variables:

static bool lt_index(
const local_variable_with_holest& a,
const local_variable_with_holest& b)
const local_variable_with_holest &a,
const local_variable_with_holest &b)
{
return a.var.index<b.var.index;
}
Expand All @@ -96,9 +124,9 @@ typedef std::map<

struct is_predecessor_oft
{
const predecessor_mapt& order;
const predecessor_mapt &order;

explicit is_predecessor_oft(const predecessor_mapt& _order) : order(_order) {}
explicit is_predecessor_oft(const predecessor_mapt &_order) : order(_order) {}

bool operator()(
local_variable_with_holest* a,
Expand Down Expand Up @@ -129,7 +157,7 @@ Function: gather_transitive_predecessors

static void gather_transitive_predecessors(
local_variable_with_holest* start,
const predecessor_mapt& predecessor_map,
const predecessor_mapt &predecessor_map,
std::set<local_variable_with_holest*>& result)
{
if(!result.insert(start).second)
Expand All @@ -156,7 +184,7 @@ Function: is_store_to_slot
\*******************************************************************/

static bool is_store_to_slot(
const java_bytecode_convert_methodt::instructiont& inst,
const java_bytecode_convert_methodt::instructiont &inst,
unsigned slotidx)
{
const std::string prevstatement=id2string(inst.statement);
Expand All @@ -167,7 +195,7 @@ static bool is_store_to_slot(
if(inst.args.size()==1)
{
// Store with an argument:
const auto& arg=inst.args[0];
const auto &arg=inst.args[0];
storeslot=id2string(to_constant_expr(arg).get_value());
}
else
Expand Down Expand Up @@ -195,7 +223,7 @@ Function: maybe_add_hole
\*******************************************************************/

static void maybe_add_hole(
local_variable_with_holest& var,
local_variable_with_holest &var,
unsigned from,
unsigned to)
{
Expand Down Expand Up @@ -271,9 +299,9 @@ static void populate_predecessor_map(
local_variable_table_with_holest::iterator firstvar,
local_variable_table_with_holest::iterator varlimit,
const std::vector<local_variable_with_holest*>& live_variable_at_address,
const address_mapt& amap,
predecessor_mapt& predecessor_map,
message_handlert& msg_handler)
const address_mapt &amap,
predecessor_mapt &predecessor_map,
message_handlert &msg_handler)
{
messaget msg(msg_handler);
for(auto it=firstvar, itend=varlimit; it!=itend; ++it)
Expand Down Expand Up @@ -385,7 +413,7 @@ Function: get_common_dominator

static unsigned get_common_dominator(
const std::set<local_variable_with_holest*>& merge_vars,
const java_cfg_dominatorst& dominator_analysis)
const java_cfg_dominatorst &dominator_analysis)
{
assert(!merge_vars.empty());

Expand All @@ -399,9 +427,9 @@ static unsigned get_common_dominator(
std::vector<unsigned> candidate_dominators;
for(auto v : merge_vars)
{
const auto& dominator_nodeidx=
const auto &dominator_nodeidx=
dominator_analysis.cfg.entry_map.at(v->var.start_pc);
const auto& this_var_doms=
const auto &this_var_doms=
dominator_analysis.cfg[dominator_nodeidx].dominators;
for(const auto this_var_dom : this_var_doms)
if(this_var_dom<=first_pc)
Expand Down Expand Up @@ -451,7 +479,7 @@ Function: populate_live_range_holes
\*******************************************************************/

static void populate_live_range_holes(
local_variable_with_holest& merge_into,
local_variable_with_holest &merge_into,
const std::set<local_variable_with_holest*>& merge_vars,
unsigned expanded_live_range_start)
{
Expand Down Expand Up @@ -489,10 +517,10 @@ Function: merge_variable_table_entries
\*******************************************************************/

static void merge_variable_table_entries(
local_variable_with_holest& merge_into,
local_variable_with_holest &merge_into,
const std::set<local_variable_with_holest*>& merge_vars,
const java_cfg_dominatorst& dominator_analysis,
std::ostream& debug_out)
const java_cfg_dominatorst &dominator_analysis,
std::ostream &debug_out)
{
// Because we need a lexically-scoped declaration,
// we must have the merged variable
Expand Down Expand Up @@ -527,7 +555,7 @@ static void merge_variable_table_entries(
#endif

// Nuke the now-subsumed var-table entries:
for(auto& v : merge_vars)
for(auto &v : merge_vars)
if(v!=&merge_into)
v->var.length=0;
}
Expand Down Expand Up @@ -557,8 +585,8 @@ Function: find_initialisers_for_slot
void java_bytecode_convert_methodt::find_initialisers_for_slot(
local_variable_table_with_holest::iterator firstvar,
local_variable_table_with_holest::iterator varlimit,
const address_mapt& amap,
const java_cfg_dominatorst& dominator_analysis)
const address_mapt &amap,
const java_cfg_dominatorst &dominator_analysis)
{
// Build a simple map from instruction PC to the variable
// live in this slot at that PC, and a map from each variable
Expand All @@ -582,7 +610,7 @@ void java_bytecode_convert_methodt::find_initialisers_for_slot(
// Now merge vartable entries according to the predecessor_map:

// Take the transitive closure of the predecessor map:
for(auto& kv : predecessor_map)
for(auto &kv : predecessor_map)
{
std::set<local_variable_with_holest*> closed_preds;
gather_transitive_predecessors(kv.first, predecessor_map, closed_preds);
Expand All @@ -609,7 +637,7 @@ void java_bytecode_convert_methodt::find_initialisers_for_slot(
if(findit==predecessor_map.end())
continue;

const auto& merge_vars=findit->second;
const auto &merge_vars=findit->second;
assert(merge_vars.size()>=2);

merge_variable_table_entries(
Expand Down Expand Up @@ -638,8 +666,8 @@ Function: walk_to_next_index
\*******************************************************************/

static void walk_to_next_index(
local_variable_table_with_holest::iterator& it1,
local_variable_table_with_holest::iterator& it2,
local_variable_table_with_holest::iterator &it1,
local_variable_table_with_holest::iterator &it2,
local_variable_table_with_holest::iterator itend)
{
if(it2==itend)
Expand Down Expand Up @@ -671,9 +699,9 @@ Function: find_initialisers
\*******************************************************************/

void java_bytecode_convert_methodt::find_initialisers(
local_variable_table_with_holest& vars,
const address_mapt& amap,
const java_cfg_dominatorst& dominator_analysis)
local_variable_table_with_holest &vars,
const address_mapt &amap,
const java_cfg_dominatorst &dominator_analysis)
{
// Sort table entries by local slot index:
std::sort(vars.begin(), vars.end(), lt_index);
Expand Down Expand Up @@ -739,17 +767,18 @@ Function: setup_local_variables
\*******************************************************************/

void java_bytecode_convert_methodt::setup_local_variables(
const methodt& m,
const address_mapt& amap)
const methodt &m,
const address_mapt &amap)
{
// Compute CFG dominator tree
java_cfg_dominatorst dominator_analysis;
dominator_analysis(amap);
method_with_amapt dominator_args(m, amap);
dominator_analysis(dominator_args);

// Find out which local variable table entries should be merged:
// Wrap each entry so we have somewhere to record live ranges with holes:
std::vector<local_variable_with_holest> vars_with_holes;
for(const auto& v : m.local_variable_table)
for(const auto &v : m.local_variable_table)
vars_with_holes.push_back({v, {}});

// Merge variable records:
Expand Down