/* - freezeset - final processing on a set of characters * * The main task here is merging identical sets. This is usually a waste * of time (although the hash code minimizes the overhead), but can win * big if REG_ICASE is being used. REG_ICASE, by the way, is why the hash * is done using addition rather than xor -- all ASCII [aA] sets xor to * the same value! */ static int /* set number */ freezeset(struct parse *p, cset *cs) { uch h = cs->hash; size_t i; cset *top = &p->g->sets[p->g->ncsets]; cset *cs2; size_t css = (size_t)p->g->csetsize; /* look for an earlier one which is the same */ for (cs2 = &p->g->sets[0]; cs2 < top; cs2++) if (cs2->hash == h && cs2 != cs) { /* maybe */ for (i = 0; i < css; i++) if (!!CHIN(cs2, i) != !!CHIN(cs, i)) break; /* no */ if (i == css) break; /* yes */ } if (cs2 < top) { /* found one */ freeset(p, cs); cs = cs2; } return((int)(cs - p->g->sets)); }
void subsetconstruct(int (*dfatable)[128], struct set *acceptset) { struct dfa *dfa; struct set *next; int nextstate = 0; int c, state; struct accept *accept; while (dfa = next_dfa()) { for (c = 0; c < MAX_CHARS; c++) { /* compute next dfa, to which dfa move on c */ next = move(dfa->states, c); next = epsilon_closure(next, &accept, 0); /* no transition */ if (!next) state = F; /* transition from current to next */ else if ((state = in_dfa(next)) >= 0) freeset(next); /* next is alloced by move()*/ else state = add_dfa(next, accept); /* real assign the dfatable: [0->ndfas][0->MAX_CHARS] */ dfatable[state_dfa(dfa)][c] = state; /* NOTE: using state, not ndfas - 1 */ if (accept) addset(acceptset, state); } } }
void free_dfa(struct dfa *dfa) { if (dfa->states) { freeset(dfa->states); dfa->states = NULL; } if (dfa->accept) { freeaccept(dfa->accept); dfa->accept = NULL; } }
/* * subset construction: * convert NFA directed graph to DFA table * * RETURN: * @table dfa state transtion table * @acceptset dfa acceptable state set * return value dfa state transtion table size */ int construct_dfa(struct nfa *sstate, int (**table)[], struct set **acceptset) { /* dfatable[STATES][CHARS] */ int (*dfatable)[MAX_CHARS]; struct set *accept; int i; /* init dfa table */ dfatable = xmalloc(MAX_TABLESIZE * sizeof(int)); /* alloc accept set */ accept = newset(); /* * init internal dfa auxiliary method, * which is used in subsetconstruct() */ init_dfas(sstate, accept); /* subset construction */ subsetconstruct(dfatable, accept); /* adjust dfatable real size */ dfatable = realloc(dfatable, ndfas * MAX_CHARS * sizeof(int)); /* return value */ if (table) *table = dfatable; else free(dfatable); if (acceptset) *acceptset = accept; else freeset(accept); return ndfas; }
/* - p_bracket - parse a bracketed character list * * Note a significant property of this code: if the allocset() did SETERROR, * no set operations are done. */ static void p_bracket(struct parse *p) { cset *cs; int invert = 0; /* Dept of Truly Sickening Special-Case Kludges */ if (p->next + 5 < p->end && strncmp(p->next, "[:<:]]", 6) == 0) { EMIT(OBOW, 0); NEXTn(6); return; } if (p->next + 5 < p->end && strncmp(p->next, "[:>:]]", 6) == 0) { EMIT(OEOW, 0); NEXTn(6); return; } if ((cs = allocset(p)) == NULL) { /* allocset did set error status in p */ return; } if (EAT('^')) invert++; /* make note to invert set at end */ if (EAT(']')) CHadd(cs, ']'); else if (EAT('-')) CHadd(cs, '-'); while (MORE() && PEEK() != ']' && !SEETWO('-', ']')) p_b_term(p, cs); if (EAT('-')) CHadd(cs, '-'); MUSTEAT(']', REG_EBRACK); if (p->error != 0) { /* don't mess things up further */ freeset(p, cs); return; } if (p->g->cflags®_ICASE) { int i; int ci; for (i = p->g->csetsize - 1; i >= 0; i--) if (CHIN(cs, i) && isalpha(i)) { ci = othercase(i); if (ci != i) CHadd(cs, ci); } if (cs->multis != NULL) mccase(p, cs); } if (invert) { int i; for (i = p->g->csetsize - 1; i >= 0; i--) if (CHIN(cs, i)) CHsub(cs, i); else CHadd(cs, i); if (p->g->cflags®_NEWLINE) CHsub(cs, '\n'); if (cs->multis != NULL) mcinvert(p, cs); } assert(cs->multis == NULL); /* xxx */ if (nch(p, cs) == 1) { /* optimize singleton sets */ ordinary(p, firstch(p, cs)); freeset(p, cs); } else EMIT(OANYOF, freezeset(p, cs)); }
void PhaseLive::compute(uint maxlrg) { _maxlrg = maxlrg; _worklist = new (_arena) Block_List(); // Init the sparse live arrays. This data is live on exit from here! // The _live info is the live-out info. _live = (IndexSet*)_arena->Amalloc(sizeof(IndexSet)*_cfg._num_blocks); uint i; for( i=0; i<_cfg._num_blocks; i++ ) { _live[i].initialize(_maxlrg); } // Init the sparse arrays for delta-sets. ResourceMark rm; // Nuke temp storage on exit // Does the memory used by _defs and _deltas get reclaimed? Does it matter? TT // Array of values defined locally in blocks _defs = NEW_RESOURCE_ARRAY(IndexSet,_cfg._num_blocks); for( i=0; i<_cfg._num_blocks; i++ ) { _defs[i].initialize(_maxlrg); } // Array of delta-set pointers, indexed by block pre_order-1. _deltas = NEW_RESOURCE_ARRAY(IndexSet*,_cfg._num_blocks); memset( _deltas, 0, sizeof(IndexSet*)* _cfg._num_blocks); _free_IndexSet = NULL; // Blocks having done pass-1 VectorSet first_pass(Thread::current()->resource_area()); // Outer loop: must compute local live-in sets and push into predecessors. uint iters = _cfg._num_blocks; // stat counters for( uint j=_cfg._num_blocks; j>0; j-- ) { Block *b = _cfg._blocks[j-1]; // Compute the local live-in set. Start with any new live-out bits. IndexSet *use = getset( b ); IndexSet *def = &_defs[b->_pre_order-1]; uint i; for( i=b->_nodes.size(); i>1; i-- ) { Node *n = b->_nodes[i-1]; if( n->is_Phi() ) break; // BoxNodes keep their input alive as long as their uses. If we // see a BoxNode then make its input live to the Root block. // Because we are solving LIVEness, the input now becomes live // over the whole procedure, interferencing with everything else // and getting a private unshared stack slot. YeeeHaw! MachNode *mach = n->is_Mach(); if( mach && mach->ideal_Opcode() == Op_Box ) getset(_cfg._broot)->insert( _names[n->in(1)->_idx] ); uint r = _names[n->_idx]; def->insert( r ); use->remove( r ); uint cnt = n->req(); for( uint k=1; k<cnt; k++ ) { Node *nk = n->in(k); uint nkidx = nk->_idx; if( _cfg._bbs[nkidx] != b ) use->insert( _names[nkidx] ); } } // Remove anything defined by Phis and the block start instruction for( uint k=i; k>0; k-- ) { uint r = _names[b->_nodes[k-1]->_idx]; def->insert( r ); use->remove( r ); } // Push these live-in things to predecessors for( uint l=1; l<b->num_preds(); l++ ) { Block *p = _cfg._bbs[b->pred(l)->_idx]; add_liveout( p, use, first_pass ); // PhiNode uses go in the live-out set of prior blocks. for( uint k=i; k>0; k-- ) add_liveout( p, _names[b->_nodes[k-1]->in(l)->_idx], first_pass ); } freeset( b ); first_pass.set(b->_pre_order); // Inner loop: blocks that picked up new live-out values to be propagated while( _worklist->size() ) { // !!!!! // #ifdef ASSERT iters++; // #endif Block *b = _worklist->pop(); IndexSet *delta = getset(b); assert( delta->count(), "missing delta set" ); // Add new-live-in to predecessors live-out sets for( uint l=1; l<b->num_preds(); l++ ) add_liveout( _cfg._bbs[b->pred(l)->_idx], delta, first_pass ); freeset(b); } // End of while-worklist-not-empty } // End of for-all-blocks-outer-loop // We explicitly clear all of the IndexSets which we are about to release. // This allows us to recycle their internal memory into IndexSet's free list. for( i=0; i<_cfg._num_blocks; i++ ) { _defs[i].clear(); if (_deltas[i]) { // Is this always true? _deltas[i]->clear(); } } IndexSet *free = _free_IndexSet; while (free != NULL) { IndexSet *temp = free; free = free->next(); temp->clear(); } }