Skip to content

Commit

Permalink
1. Use a new tbb::concurrent_hash_map to record block end.
Browse files Browse the repository at this point in the history
   In addition, when adding out-going edges to a block, we
   first query the block end hash map to get the accessor
   to the block. When splitting the block, we also first
   query the block end hash map to get the access to the block.
   tbb::concurrent_hash_map provides implicit read-write lock
   through the accessor. Therefore, we enforce that adding
   out-going edges are not going to be concurrent with block split.

2. Add a bunch of asserts that check edge consistency. This is
   for debug purpose and will be removed later
  • Loading branch information
mxz297 committed Oct 16, 2018
1 parent 71e14a7 commit 0777c24
Show file tree
Hide file tree
Showing 5 changed files with 258 additions and 115 deletions.
5 changes: 4 additions & 1 deletion parseAPI/h/CFG.h
Expand Up @@ -417,7 +417,10 @@ inline void Block::addTarget(Edge * e)
if(e->type() == FALLTHROUGH ||
e->type() == COND_NOT_TAKEN)
{
assert(e->_target_off >= end());
assert(e->_target_off == end());
}
for (auto eit = _trglist.begin(); eit != _trglist.end(); ++eit) {
assert( (*eit)->trg_addr() != e->trg_addr() || (*eit)->type() != e->type());
}
_trglist.push_back(e);
}
Expand Down
20 changes: 16 additions & 4 deletions parseAPI/src/ParseData.C
Expand Up @@ -500,21 +500,33 @@ OverlappingParseData::reglookup(CodeRegion *cr, Address /* addr */)
return cr;
}

Function*
OverlappingParseData::setEdgeParsingStatus(CodeRegion *cr, Address addr, Function *f)
edge_parsing_data
OverlappingParseData::setEdgeParsingStatus(CodeRegion *cr, Address addr, Function *f, Block *b)
{
boost::lock_guard<ParseData> g(*this);
if(!HASHDEF(rmap,cr)) {
fprintf(stderr,"Error, invalid code region [%lx,%lx) in remove_frame\n",
cr->offset(),cr->offset()+cr->length());
return NULL;
return edge_parsing_data();
}
region_data * rd = rmap[cr];
return rd->set_edge_parsed(addr,f);
return rd->set_edge_parsed(addr,f, b);
}

void
OverlappingParseData::getAllRegionData(vector<region_data*> &rds) {
for (auto rit = rmap.begin(); rit != rmap.end(); ++rit)
rds.push_back(rit->second);
}

region_data::edge_data_map*
OverlappingParseData::get_edge_data_map(CodeRegion *cr) {
boost::lock_guard<ParseData> g(*this);
if(!HASHDEF(rmap,cr)) {
fprintf(stderr,"Error, invalid code region [%lx,%lx) in remove_frame\n",
cr->offset(),cr->offset()+cr->length());
return NULL;
}
region_data * rd = rmap[cr];
return rd->get_edge_data_map();
}
51 changes: 40 additions & 11 deletions parseAPI/src/ParseData.h
Expand Up @@ -139,7 +139,7 @@ class ParseFrame : public boost::lockable_adapter<boost::recursive_mutex> {
CodeRegion * codereg;

ParseWorkElem * seed; // stored for cleanup
std::vector<Block*> value_driven_jump_tables;
std::set<Address> value_driven_jump_tables;

ParseFrame(Function * f,ParseData *pd) :
curAddr(0),
Expand Down Expand Up @@ -172,6 +172,19 @@ class ParseFrame : public boost::lockable_adapter<boost::recursive_mutex> {
ParseData * _pd;
};

class edge_parsing_data {

public:
Block* b;
Function *f;
edge_parsing_data(Function *ff, Block *bb) {
b = bb;
f = ff;
}
edge_parsing_data() : b(NULL), f(NULL) {}
};


/* per-CodeRegion parsing data */
class region_data {
public:
Expand All @@ -189,7 +202,8 @@ class region_data {

// Edge parsing records
// We only want one thread to create edges for a location
tbb::concurrent_hash_map<Address, Function*> edge_parsing_status;
typedef tbb::concurrent_hash_map<Address, edge_parsing_data> edge_data_map;
edge_data_map edge_parsing_status;

Function * findFunc(Address entry);
Block * findBlock(Address entry);
Expand Down Expand Up @@ -295,20 +309,26 @@ class region_data {
blocksByRange.insert(sink);
}

Function* set_edge_parsed(Address addr, Function *f) {
Function* ret=NULL;
edge_data_map* get_edge_data_map() { return &edge_parsing_status; }

edge_parsing_data set_edge_parsed(Address addr, Function *f, Block *b) {
edge_parsing_data ret;
race_detector_fake_lock_acquire(race_detector_fake_lock(edge_parsing_status));
{
tbb::concurrent_hash_map<Address, Function*>::accessor a;
tbb::concurrent_hash_map<Address, edge_parsing_data>::accessor a;
// A successful insertion means the thread should
// continue to create edges. We return the passed in Function*
// as indication of successful insertion.
//
// Otherwise, another thread has started creating edges.
// The current thread should give up. We return
// the function who succeeded.
if (!edge_parsing_status.insert(a, make_pair(addr, f)))
if (!edge_parsing_status.insert(a, addr))
ret = a->second;
else {
ret.f = f;
ret.b = b;
}
}
race_detector_fake_lock_release(race_detector_fake_lock(edge_parsing_status));
return ret;
Expand Down Expand Up @@ -433,8 +453,10 @@ class ParseData : public boost::lockable_adapter<boost::recursive_mutex> {
// does the Right Thing(TM) for standard- and overlapping-region
// object types
virtual CodeRegion * reglookup(CodeRegion *cr, Address addr) =0;
virtual Function* setEdgeParsingStatus(CodeRegion *cr, Address addr, Function *f) = 0;
virtual edge_parsing_data setEdgeParsingStatus(CodeRegion *cr, Address addr, Function *f, Block *b) = 0;
virtual void getAllRegionData(std::vector<region_data*>&) = 0;
virtual region_data::edge_data_map* get_edge_data_map(CodeRegion*) = 0;

};

/* StandardParseData represents parse data for Parsers that disallow
Expand Down Expand Up @@ -472,8 +494,9 @@ class StandardParseData : public ParseData {
void remove_extents(const std::vector<FuncExtent*> &extents);

CodeRegion * reglookup(CodeRegion *cr, Address addr);
Function* setEdgeParsingStatus(CodeRegion *cr, Address addr, Function *f);
edge_parsing_data setEdgeParsingStatus(CodeRegion *cr, Address addr, Function *f, Block *b);
void getAllRegionData(std::vector<region_data*>& rds);
region_data::edge_data_map* get_edge_data_map(CodeRegion* cr);

};

Expand All @@ -490,14 +513,18 @@ inline Block* StandardParseData::record_block(CodeRegion * /* cr */, Block *b)
return _rdata.record_block(b);
}

inline Function* StandardParseData::setEdgeParsingStatus(CodeRegion *, Address addr, Function *f)
inline edge_parsing_data StandardParseData::setEdgeParsingStatus(CodeRegion *, Address addr, Function *f, Block *b)
{
return _rdata.set_edge_parsed(addr, f);
return _rdata.set_edge_parsed(addr, f, b);
}

inline void StandardParseData::getAllRegionData(std::vector<region_data*> & rds) {
rds.push_back(&_rdata);
}
inline region_data::edge_data_map* StandardParseData::get_edge_data_map(CodeRegion*) {
return _rdata.get_edge_data_map();
}


/* OverlappingParseData handles binary code objects like .o files
where CodeRegions may overlap on the same linear address space */
Expand Down Expand Up @@ -535,8 +562,10 @@ class OverlappingParseData : public ParseData {
void remove_extents(const std::vector<FuncExtent*> &extents);

CodeRegion * reglookup(CodeRegion *cr, Address addr);
Function* setEdgeParsingStatus(CodeRegion *cr, Address addr, Function* f);
edge_parsing_data setEdgeParsingStatus(CodeRegion *cr, Address addr, Function* f, Block *b);
void getAllRegionData(std::vector<region_data*>&);
region_data::edge_data_map* get_edge_data_map(CodeRegion* cr);

};

}
Expand Down

0 comments on commit 0777c24

Please sign in to comment.