Skip to content

Commit 2343bec

Browse files
author
Daniel Kroening
authored
Merge pull request #466 from smowton/exception_edges_for_live_range_analysis_master
Exception edges for live range analysis master
2 parents ecdf609 + 92e1e4a commit 2343bec

4 files changed

+90
-49
lines changed

src/java_bytecode/java_bytecode_convert_method_class.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,8 @@ class java_bytecode_convert_methodt:public messaget
129129

130130
public:
131131
typedef std::map<unsigned, converted_instructiont> address_mapt;
132-
typedef cfg_dominators_templatet<const address_mapt, unsigned, false>
132+
typedef std::pair<const methodt&, const address_mapt&> method_with_amapt;
133+
typedef cfg_dominators_templatet<method_with_amapt, unsigned, false>
133134
java_cfg_dominatorst;
134135

135136
protected:

src/java_bytecode/java_bytecode_parse_tree.h

+5-1
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,12 @@ class java_bytecode_parse_treet
8282
return instructions.back();
8383
}
8484

85-
class exceptiont
85+
struct exceptiont
8686
{
87+
std::size_t start_pc;
88+
std::size_t end_pc;
89+
std::size_t handler_pc;
90+
symbol_typet catch_type;
8791
};
8892

8993
typedef std::vector<exceptiont> exception_tablet;

src/java_bytecode/java_bytecode_parser.cpp

+11-4
Original file line numberDiff line numberDiff line change
@@ -968,13 +968,20 @@ void java_bytecode_parsert::rmethod_attribute(methodt &method)
968968
rbytecode(method.instructions);
969969

970970
u2 exception_table_length=read_u2();
971+
method.exception_table.resize(exception_table_length);
971972

972973
for(std::size_t e=0; e<exception_table_length; e++)
973974
{
974-
u2 UNUSED start_pc=read_u2();
975-
u2 UNUSED end_pc=read_u2();
976-
u2 UNUSED handler_pc=read_u2();
977-
u2 UNUSED catch_type=read_u2();
975+
u2 start_pc=read_u2();
976+
u2 end_pc=read_u2();
977+
u2 handler_pc=read_u2();
978+
u2 catch_type=read_u2();
979+
method.exception_table[e].start_pc=start_pc;
980+
method.exception_table[e].end_pc=end_pc;
981+
method.exception_table[e].handler_pc=handler_pc;
982+
if(catch_type!=0)
983+
method.exception_table[e].catch_type=
984+
to_symbol_type(pool_entry(catch_type).expr.type());
978985
}
979986

980987
u2 attributes_count=read_u2();

src/java_bytecode/java_local_variable_table.cpp

+72-43
Original file line numberDiff line numberDiff line change
@@ -20,43 +20,71 @@ Author: Chris Smowton, [email protected]
2020
template<class T>
2121
struct procedure_local_cfg_baset<
2222
T,
23-
const java_bytecode_convert_methodt::address_mapt,
23+
java_bytecode_convert_methodt::method_with_amapt,
2424
unsigned> :
2525
public graph<cfg_base_nodet<T, unsigned> >
2626
{
27-
typedef java_bytecode_convert_methodt::address_mapt address_mapt;
27+
typedef java_bytecode_convert_methodt::method_with_amapt method_with_amapt;
2828
typedef std::map<unsigned, unsigned> entry_mapt;
2929
entry_mapt entry_map;
3030

3131
procedure_local_cfg_baset() {}
3232

33-
void operator()(const address_mapt& amap)
33+
void operator()(const method_with_amapt &args)
3434
{
35-
for(const auto& inst : amap)
35+
const auto &method=args.first;
36+
const auto &amap=args.second;
37+
for(const auto &inst : amap)
3638
{
3739
// Map instruction PCs onto node indices:
3840
entry_map[inst.first]=this->add_node();
3941
// Map back:
4042
(*this)[entry_map[inst.first]].PC=inst.first;
4143
}
42-
for(const auto& inst : amap)
44+
// Add edges declared in the address map:
45+
for(const auto &inst : amap)
4346
{
4447
for(auto succ : inst.second.successors)
4548
this->add_edge(entry_map.at(inst.first), entry_map.at(succ));
4649
}
50+
// Next, add edges declared in the exception table, which
51+
// don't figure in the address map successors/predecessors as yet:
52+
for(const auto &table_entry : method.exception_table)
53+
{
54+
auto findit=amap.find(table_entry.start_pc);
55+
assert(findit!=amap.end() &&
56+
"Exception table entry doesn't point to an instruction?");
57+
for(; findit->first<table_entry.end_pc; ++findit)
58+
{
59+
// For now just assume any non-branch
60+
// instruction could potentially throw.
61+
auto succit=findit;
62+
++succit;
63+
if(succit==amap.end())
64+
continue;
65+
const auto &thisinst=findit->second;
66+
if(thisinst.successors.size()==1 &&
67+
thisinst.successors.back()==succit->first)
68+
{
69+
this->add_edge(
70+
entry_map.at(findit->first),
71+
entry_map.at(table_entry.handler_pc));
72+
}
73+
}
74+
}
4775
}
4876

49-
unsigned get_first_node(const address_mapt& amap) const
77+
unsigned get_first_node(const method_with_amapt &args) const
5078
{
51-
return amap.begin()->first;
79+
return args.second.begin()->first;
5280
}
53-
unsigned get_last_node(const address_mapt& amap) const
81+
unsigned get_last_node(const method_with_amapt &args) const
5482
{
55-
return (--amap.end())->first;
83+
return (--args.second.end())->first;
5684
}
57-
unsigned nodes_empty(const address_mapt& amap) const
85+
unsigned nodes_empty(const method_with_amapt &args) const
5886
{
59-
return amap.empty();
87+
return args.second.empty();
6088
}
6189
};
6290

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

77105
static bool lt_index(
78-
const local_variable_with_holest& a,
79-
const local_variable_with_holest& b)
106+
const local_variable_with_holest &a,
107+
const local_variable_with_holest &b)
80108
{
81109
return a.var.index<b.var.index;
82110
}
@@ -96,9 +124,9 @@ typedef std::map<
96124

97125
struct is_predecessor_oft
98126
{
99-
const predecessor_mapt& order;
127+
const predecessor_mapt &order;
100128

101-
explicit is_predecessor_oft(const predecessor_mapt& _order) : order(_order) {}
129+
explicit is_predecessor_oft(const predecessor_mapt &_order) : order(_order) {}
102130

103131
bool operator()(
104132
local_variable_with_holest* a,
@@ -129,7 +157,7 @@ Function: gather_transitive_predecessors
129157

130158
static void gather_transitive_predecessors(
131159
local_variable_with_holest* start,
132-
const predecessor_mapt& predecessor_map,
160+
const predecessor_mapt &predecessor_map,
133161
std::set<local_variable_with_holest*>& result)
134162
{
135163
if(!result.insert(start).second)
@@ -156,7 +184,7 @@ Function: is_store_to_slot
156184
\*******************************************************************/
157185

158186
static bool is_store_to_slot(
159-
const java_bytecode_convert_methodt::instructiont& inst,
187+
const java_bytecode_convert_methodt::instructiont &inst,
160188
unsigned slotidx)
161189
{
162190
const std::string prevstatement=id2string(inst.statement);
@@ -167,7 +195,7 @@ static bool is_store_to_slot(
167195
if(inst.args.size()==1)
168196
{
169197
// Store with an argument:
170-
const auto& arg=inst.args[0];
198+
const auto &arg=inst.args[0];
171199
storeslot=id2string(to_constant_expr(arg).get_value());
172200
}
173201
else
@@ -195,7 +223,7 @@ Function: maybe_add_hole
195223
\*******************************************************************/
196224

197225
static void maybe_add_hole(
198-
local_variable_with_holest& var,
226+
local_variable_with_holest &var,
199227
unsigned from,
200228
unsigned to)
201229
{
@@ -271,9 +299,9 @@ static void populate_predecessor_map(
271299
local_variable_table_with_holest::iterator firstvar,
272300
local_variable_table_with_holest::iterator varlimit,
273301
const std::vector<local_variable_with_holest*>& live_variable_at_address,
274-
const address_mapt& amap,
275-
predecessor_mapt& predecessor_map,
276-
message_handlert& msg_handler)
302+
const address_mapt &amap,
303+
predecessor_mapt &predecessor_map,
304+
message_handlert &msg_handler)
277305
{
278306
messaget msg(msg_handler);
279307
for(auto it=firstvar, itend=varlimit; it!=itend; ++it)
@@ -385,7 +413,7 @@ Function: get_common_dominator
385413

386414
static unsigned get_common_dominator(
387415
const std::set<local_variable_with_holest*>& merge_vars,
388-
const java_cfg_dominatorst& dominator_analysis)
416+
const java_cfg_dominatorst &dominator_analysis)
389417
{
390418
assert(!merge_vars.empty());
391419

@@ -399,9 +427,9 @@ static unsigned get_common_dominator(
399427
std::vector<unsigned> candidate_dominators;
400428
for(auto v : merge_vars)
401429
{
402-
const auto& dominator_nodeidx=
430+
const auto &dominator_nodeidx=
403431
dominator_analysis.cfg.entry_map.at(v->var.start_pc);
404-
const auto& this_var_doms=
432+
const auto &this_var_doms=
405433
dominator_analysis.cfg[dominator_nodeidx].dominators;
406434
for(const auto this_var_dom : this_var_doms)
407435
if(this_var_dom<=first_pc)
@@ -451,7 +479,7 @@ Function: populate_live_range_holes
451479
\*******************************************************************/
452480

453481
static void populate_live_range_holes(
454-
local_variable_with_holest& merge_into,
482+
local_variable_with_holest &merge_into,
455483
const std::set<local_variable_with_holest*>& merge_vars,
456484
unsigned expanded_live_range_start)
457485
{
@@ -489,10 +517,10 @@ Function: merge_variable_table_entries
489517
\*******************************************************************/
490518

491519
static void merge_variable_table_entries(
492-
local_variable_with_holest& merge_into,
520+
local_variable_with_holest &merge_into,
493521
const std::set<local_variable_with_holest*>& merge_vars,
494-
const java_cfg_dominatorst& dominator_analysis,
495-
std::ostream& debug_out)
522+
const java_cfg_dominatorst &dominator_analysis,
523+
std::ostream &debug_out)
496524
{
497525
// Because we need a lexically-scoped declaration,
498526
// we must have the merged variable
@@ -527,7 +555,7 @@ static void merge_variable_table_entries(
527555
#endif
528556

529557
// Nuke the now-subsumed var-table entries:
530-
for(auto& v : merge_vars)
558+
for(auto &v : merge_vars)
531559
if(v!=&merge_into)
532560
v->var.length=0;
533561
}
@@ -557,8 +585,8 @@ Function: find_initialisers_for_slot
557585
void java_bytecode_convert_methodt::find_initialisers_for_slot(
558586
local_variable_table_with_holest::iterator firstvar,
559587
local_variable_table_with_holest::iterator varlimit,
560-
const address_mapt& amap,
561-
const java_cfg_dominatorst& dominator_analysis)
588+
const address_mapt &amap,
589+
const java_cfg_dominatorst &dominator_analysis)
562590
{
563591
// Build a simple map from instruction PC to the variable
564592
// live in this slot at that PC, and a map from each variable
@@ -582,7 +610,7 @@ void java_bytecode_convert_methodt::find_initialisers_for_slot(
582610
// Now merge vartable entries according to the predecessor_map:
583611

584612
// Take the transitive closure of the predecessor map:
585-
for(auto& kv : predecessor_map)
613+
for(auto &kv : predecessor_map)
586614
{
587615
std::set<local_variable_with_holest*> closed_preds;
588616
gather_transitive_predecessors(kv.first, predecessor_map, closed_preds);
@@ -609,7 +637,7 @@ void java_bytecode_convert_methodt::find_initialisers_for_slot(
609637
if(findit==predecessor_map.end())
610638
continue;
611639

612-
const auto& merge_vars=findit->second;
640+
const auto &merge_vars=findit->second;
613641
assert(merge_vars.size()>=2);
614642

615643
merge_variable_table_entries(
@@ -638,8 +666,8 @@ Function: walk_to_next_index
638666
\*******************************************************************/
639667

640668
static void walk_to_next_index(
641-
local_variable_table_with_holest::iterator& it1,
642-
local_variable_table_with_holest::iterator& it2,
669+
local_variable_table_with_holest::iterator &it1,
670+
local_variable_table_with_holest::iterator &it2,
643671
local_variable_table_with_holest::iterator itend)
644672
{
645673
if(it2==itend)
@@ -671,9 +699,9 @@ Function: find_initialisers
671699
\*******************************************************************/
672700

673701
void java_bytecode_convert_methodt::find_initialisers(
674-
local_variable_table_with_holest& vars,
675-
const address_mapt& amap,
676-
const java_cfg_dominatorst& dominator_analysis)
702+
local_variable_table_with_holest &vars,
703+
const address_mapt &amap,
704+
const java_cfg_dominatorst &dominator_analysis)
677705
{
678706
// Sort table entries by local slot index:
679707
std::sort(vars.begin(), vars.end(), lt_index);
@@ -739,17 +767,18 @@ Function: setup_local_variables
739767
\*******************************************************************/
740768

741769
void java_bytecode_convert_methodt::setup_local_variables(
742-
const methodt& m,
743-
const address_mapt& amap)
770+
const methodt &m,
771+
const address_mapt &amap)
744772
{
745773
// Compute CFG dominator tree
746774
java_cfg_dominatorst dominator_analysis;
747-
dominator_analysis(amap);
775+
method_with_amapt dominator_args(m, amap);
776+
dominator_analysis(dominator_args);
748777

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

755784
// Merge variable records:

0 commit comments

Comments
 (0)