Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Concurrency/Actors.cpp

    ra8e8c67 r34ed17b  
    2121#include "AST/TranslationUnit.hpp"
    2222#include "AST/Expr.hpp"
    23 #include <algorithm>
    2423using namespace ast;
    25 using namespace std;
    2624
    2725namespace Concurrency {
    2826
    2927struct CollectactorStructDecls : public ast::WithGuards {
    30     unordered_set<const StructDecl *> & actorStructDecls;
    31     unordered_set<const StructDecl *>  & messageStructDecls;
     28    std::map<const StructDecl *, int> & actorStructDecls;
     29    std::map<const StructDecl *, int>  & messageStructDecls;
    3230    const StructDecl ** requestDecl;
    3331    const EnumDecl ** allocationDecl;
     
    3634    StructDecl * parentDecl;
    3735    bool insideStruct = false;
    38     bool namedDecl = false;
    39 
    40     // finds and sets a ptr to the Allocation enum, which is needed in the next pass
     36
    4137    void previsit( const EnumDecl * decl ) {
    4238        if( decl->name == "Allocation" ) *allocationDecl = decl;
    4339    }
    4440
    45     // finds and sets a ptr to the actor, message, and request structs, which are needed in the next pass
    4641    void previsit( const StructDecl * decl ) {
    4742        GuardValue(insideStruct);
     
    5045        if( decl->name == "actor" ) *actorDecl = decl;
    5146        if( decl->name == "message" ) *msgDecl = decl;
    52         if( decl->name == "request" ) *requestDecl = decl;
     47        if( decl->name == "request" ) *requestDecl = decl;       
    5348        }
    5449
    55     // this catches structs of the form:
    56     //     struct dummy_actor { actor a; };
    57     // since they should be:
    58     //     struct dummy_actor { inline actor; };
    59     void previsit ( const ObjectDecl * decl ) {
    60         if ( insideStruct && ! decl->name.empty() ) {
    61             GuardValue(namedDecl);
    62             namedDecl = true;
    63         }
    64     }
    65 
    66     // this collects the valid actor and message struct decl pts
    6750    void postvisit( const StructInstType * node ) {
    6851        if ( ! *actorDecl || ! *msgDecl ) return;
    69         if ( insideStruct && !namedDecl ) {
     52        if ( insideStruct ) {
    7053            if ( node->aggr() == *actorDecl ) {
    71                 actorStructDecls.insert( parentDecl );
     54                actorStructDecls.insert({parentDecl, 1});
    7255            } else if ( node->aggr() == *msgDecl ) {
    73                 messageStructDecls.insert( parentDecl );
     56                messageStructDecls.insert({parentDecl, 1});
    7457            }
    7558        }
     
    7760
    7861  public:
    79     CollectactorStructDecls( unordered_set<const StructDecl *> & actorStructDecls, unordered_set<const StructDecl *> & messageStructDecls,
     62    CollectactorStructDecls( std::map<const StructDecl *, int> & actorStructDecls, std::map<const StructDecl *, int> & messageStructDecls,
    8063        const StructDecl ** requestDecl, const EnumDecl ** allocationDecl, const StructDecl ** actorDecl, const StructDecl ** msgDecl )
    8164        : actorStructDecls( actorStructDecls ), messageStructDecls( messageStructDecls ), requestDecl( requestDecl ),
     
    8366};
    8467
    85 // keeps track of all fwdDecls of message routines so that we can hoist them to right after the appropriate decls
    86 class FwdDeclTable {
    87 
    88     // tracks which decls we have seen so that we can hoist the FunctionDecl to the highest point possible
    89     struct FwdDeclData {
    90         const StructDecl * actorDecl;
    91         const StructDecl * msgDecl;
    92         FunctionDecl * fwdDecl;
    93         bool actorFound;
    94         bool msgFound;
    95 
    96         bool readyToInsert() { return actorFound && msgFound; }
    97         bool foundActor() { actorFound = true; return readyToInsert(); }
    98         bool foundMsg() { msgFound = true; return readyToInsert(); }
    99 
    100         FwdDeclData( const StructDecl * actorDecl, const StructDecl * msgDecl, FunctionDecl * fwdDecl ) :
    101             actorDecl(actorDecl), msgDecl(msgDecl), fwdDecl(fwdDecl), actorFound(false), msgFound(false) {}
    102     };
    103 
    104     // map indexed by actor struct ptr
    105     // value is map of all FwdDeclData that contains said actor struct ptr
    106     // inner map is indexed by the message struct ptr of FwdDeclData
    107     unordered_map<const StructDecl *, unordered_map<const StructDecl *, FwdDeclData *>> actorMap;
    108 
    109     // this map is the same except the outer map is indexed by message ptr and the inner is indexed by actor ptr
    110     unordered_map<const StructDecl *, unordered_map<const StructDecl *, FwdDeclData *>> msgMap;
    111 
    112     void insert( const StructDecl * decl, const StructDecl * otherDecl, unordered_map<const StructDecl *, unordered_map<const StructDecl *, FwdDeclData *>> & map, FwdDeclData * data ) {
    113         auto iter = map.find( decl );
    114         if ( iter != map.end() ) { // if decl exists in map append data to existing inner map
    115             iter->second.emplace( make_pair( otherDecl, data ) );
    116         } else { // else create inner map for key
    117             map.emplace( make_pair( decl, unordered_map<const StructDecl *, FwdDeclData *>( { make_pair( otherDecl, data ) } ) ) );
    118         }
    119     }
    120 
    121   public:
    122     // insert decl into table so that we can fwd declare it later (average cost: O(1))
    123     void insertDecl( const StructDecl * actorDecl, const StructDecl * msgDecl, FunctionDecl * fwdDecl ) {
    124         FwdDeclData * declToInsert = new FwdDeclData( actorDecl, msgDecl, fwdDecl );
    125         insert( actorDecl, msgDecl, actorMap, declToInsert );
    126         insert( msgDecl, actorDecl, msgMap, declToInsert );
    127     }
    128 
    129     // returns list of decls to insert after current struct decl
    130     // Over the entire pass the runtime of this routine is O(r) where r is the # of receive routines
    131     list<FunctionDecl *> updateDecl( const StructDecl * decl, bool isMsg ) {
    132         unordered_map<const StructDecl *, unordered_map<const StructDecl *, FwdDeclData *>> & map = isMsg ? msgMap : actorMap;
    133         unordered_map<const StructDecl *, unordered_map<const StructDecl *, FwdDeclData *>> & otherMap =  isMsg ? actorMap : msgMap;
    134         auto iter = map.find( decl );
    135         list<FunctionDecl *> toInsertAfter; // this is populated with decls that are ready to insert
    136         if ( iter == map.end() ) return toInsertAfter;
    137        
    138         // iterate over inner map
    139         unordered_map<const StructDecl *, FwdDeclData *> & currInnerMap = iter->second;
    140         for ( auto innerIter = currInnerMap.begin(); innerIter != currInnerMap.end(); ) {
    141             FwdDeclData * currentDatum = innerIter->second;
    142             bool readyToInsert = isMsg ? currentDatum->foundMsg() : currentDatum->foundActor();
    143             if ( ! readyToInsert ) { ++innerIter; continue; }
    144            
    145             // readyToInsert is true so we are good to insert the forward decl of the message fn
    146             toInsertAfter.push_back( currentDatum->fwdDecl );
    147 
    148             // need to remove from other map before deleting
    149             // find inner map in other map ( other map is actor map if original is msg map and vice versa )
    150             const StructDecl * otherDecl = isMsg ? currentDatum->actorDecl : currentDatum->msgDecl;
    151             auto otherMapIter = otherMap.find( otherDecl );
    152 
    153             unordered_map<const StructDecl *, FwdDeclData *> & otherInnerMap = otherMapIter->second;
    154 
    155             // find the FwdDeclData we need to remove in the other inner map
    156             auto otherInnerIter = otherInnerMap.find( decl );
    157 
    158             // remove references to deleted FwdDeclData from current inner map
    159             innerIter = currInnerMap.erase( innerIter ); // this does the increment so no explicit inc needed
    160 
    161             // remove references to deleted FwdDeclData from other inner map
    162             otherInnerMap.erase( otherInnerIter );
    163            
    164             // if other inner map is now empty, remove key from other outer map
    165             if ( otherInnerMap.empty() )
    166                 otherMap.erase( otherDecl );
    167 
    168             // now we are safe to delete the FwdDeclData since we are done with it
    169             // and we have removed all references to it from our data structures
    170             delete currentDatum;
    171         }
    172 
    173         // if current inner map is now empty, remove key from outer map.
    174         // Have to do this after iterating for safety
    175         if ( currInnerMap.empty() )
    176             map.erase( decl );
    177 
    178         return toInsertAfter;
    179     }
    180 };
    181 
    18268struct GenReceiveDecls : public ast::WithDeclsToAdd<> {
    183     unordered_set<const StructDecl *> & actorStructDecls;
    184     unordered_set<const StructDecl *>  & messageStructDecls;
     69    std::map<const StructDecl *, int> & actorStructDecls;
     70    std::map<const StructDecl *, int>  & messageStructDecls;
    18571    const StructDecl ** requestDecl;
    18672    const EnumDecl ** allocationDecl;
    18773    const StructDecl ** actorDecl;
    18874    const StructDecl ** msgDecl;
    189     FwdDeclTable & forwardDecls;
     75    std::vector<FunctionDecl *> & forwardDecls;
    19076
    19177        void postvisit( const FunctionDecl * decl ) {
     
    20490
    20591        // If the struct instances are derived actor and message types then generate the message send routine
    206         auto actorIter = actorStructDecls.find( arg1InstType->aggr() );
    207         auto messageIter = messageStructDecls.find( arg2InstType->aggr() );
    208         if ( actorIter != actorStructDecls.end() && messageIter != messageStructDecls.end() ) {
     92        if ( actorStructDecls.count( arg1InstType->aggr() ) && messageStructDecls.count( arg2InstType->aggr() ) ) {
    20993
    21094            // check that we have found all the decls we need from <actor.hfa>
     
    341225           
    342226            // forward decls to resolve use before decl problem for '|' routines
    343             forwardDecls.insertDecl( *actorIter, *messageIter , ast::deepCopy( sendOperatorFunction ) );
    344             // forwardDecls.push_back( ast::deepCopy( sendOperatorFunction ) );
     227            forwardDecls.push_back( ast::deepCopy( sendOperatorFunction ) );
    345228
    346229            sendOperatorFunction->stmts = sendBody;
     
    350233
    351234  public:
    352     GenReceiveDecls( unordered_set<const StructDecl *> & actorStructDecls, unordered_set<const StructDecl *> & messageStructDecls,
     235    GenReceiveDecls( std::map<const StructDecl *, int> & actorStructDecls, std::map<const StructDecl *, int> & messageStructDecls,
    353236        const StructDecl ** requestDecl, const EnumDecl ** allocationDecl, const StructDecl ** actorDecl, const StructDecl ** msgDecl,
    354         FwdDeclTable & forwardDecls ) : actorStructDecls(actorStructDecls), messageStructDecls(messageStructDecls),
     237        std::vector<FunctionDecl *> & forwardDecls ) : actorStructDecls(actorStructDecls), messageStructDecls(messageStructDecls),
    355238        requestDecl(requestDecl), allocationDecl(allocationDecl), actorDecl(actorDecl), msgDecl(msgDecl), forwardDecls(forwardDecls) {}
    356239};
    357240
    358241struct GenFwdDecls : public ast::WithDeclsToAdd<> {
    359     unordered_set<const StructDecl *> & actorStructDecls;
    360     unordered_set<const StructDecl *>  & messageStructDecls;
    361     FwdDeclTable & forwardDecls;
    362 
    363     void postvisit( const StructDecl * decl ) {
    364         list<FunctionDecl *> toAddAfter;
    365         auto actorIter = actorStructDecls.find( decl );
    366         if ( actorIter != actorStructDecls.end() ) { // this is a derived actor decl
    367             // get list of fwd decls that we can now insert
    368             toAddAfter = forwardDecls.updateDecl( decl, false );
    369 
    370             // get rid of decl from actorStructDecls since we no longer need it
    371             actorStructDecls.erase( actorIter );
    372         } else {
    373             auto messageIter = messageStructDecls.find( decl );
    374             if ( messageIter == messageStructDecls.end() ) return;
    375 
    376             toAddAfter = forwardDecls.updateDecl( decl, true );
    377 
    378             // get rid of decl from messageStructDecls since we no longer need it
    379             messageStructDecls.erase( messageIter );
    380         }
    381 
    382         // add the fwd decls to declsToAddAfter
    383         for ( FunctionDecl * func : toAddAfter ) {
    384             declsToAddAfter.push_back( func );
     242    std::map<const StructDecl *, int> & actorStructDecls;
     243    std::map<const StructDecl *, int>  & messageStructDecls;
     244    std::vector<FunctionDecl *> & forwardDecls;
     245    bool done;
     246
     247    void postvisit( const FunctionDecl * decl ) {
     248        if ( done ) return;
     249        // return if not of the form receive( param1, param2 ) or if it is a forward decl
     250        if ( decl->name != "receive" || decl->params.size() != 2 || !decl->stmts ) return;
     251
     252        // the params should be references
     253        const ReferenceType * derivedActorRef = dynamic_cast<const ReferenceType *>(decl->params.at(0)->get_type());
     254        const ReferenceType * derivedMsgRef = dynamic_cast<const ReferenceType *>(decl->params.at(1)->get_type());
     255        if ( !derivedActorRef || !derivedMsgRef ) return;
     256
     257        // the references should be to struct instances
     258        const StructInstType * arg1InstType = dynamic_cast<const StructInstType *>(derivedActorRef->base.get());
     259        const StructInstType * arg2InstType = dynamic_cast<const StructInstType *>(derivedMsgRef->base.get());
     260        if ( !arg1InstType || !arg2InstType ) return;
     261
     262        // If the struct instances are derived actor and message types then generate the message send routine
     263        if ( actorStructDecls.count( arg1InstType->aggr() ) && messageStructDecls.count( arg2InstType->aggr() ) ) {
     264            done = true;
     265            for ( const auto & func : forwardDecls ) {
     266                declsToAddBefore.push_back( func );
     267            }
    385268        }
    386269    }
    387270
    388271  public:
    389     GenFwdDecls( unordered_set<const StructDecl *> & actorStructDecls, unordered_set<const StructDecl *> & messageStructDecls,
    390         FwdDeclTable & forwardDecls ) : actorStructDecls(actorStructDecls), messageStructDecls(messageStructDecls),
    391         forwardDecls(forwardDecls) {}
     272    GenFwdDecls( std::map<const StructDecl *, int> & actorStructDecls, std::map<const StructDecl *, int> & messageStructDecls,
     273        std::vector<FunctionDecl *> & forwardDecls ) : actorStructDecls(actorStructDecls), messageStructDecls(messageStructDecls),
     274        forwardDecls(forwardDecls), done(false) {}
    392275};
    393276
    394277void implementActors( TranslationUnit & translationUnit ) {
    395     // unordered_maps to collect all derived actor and message types
    396     unordered_set<const StructDecl *> actorStructDecls;
    397     unordered_set<const StructDecl *> messageStructDecls;
    398     FwdDeclTable forwardDecls;
     278    // maps to collect all derived actor and message types
     279    std::map<const StructDecl *, int> actorStructDecls;
     280    std::map<const StructDecl *, int> messageStructDecls;
     281    std::vector<FunctionDecl *> forwardDecls;
    399282
    400283    // for storing through the passes
Note: See TracChangeset for help on using the changeset viewer.