| OLD | NEW | 
|---|
| (Empty) |  | 
|  | 1 GT2 patch as found in ragel-6-gt2 branch. | 
|  | 2 | 
|  | 3 More info: http://www.complang.org/pipermail/ragel-users/2012-May/002831.html | 
|  | 4 | 
|  | 5 --- ragel/cdgoto.cpp | 
|  | 6 +++ ragel/cdgoto.cpp | 
|  | 7 @@ -34,6 +34,11 @@ | 
|  | 8         return out; | 
|  | 9  } | 
|  | 10 | 
|  | 11 +int GotoCodeGen::TRANS_NR( RedTransAp *trans ) | 
|  | 12 +{ | 
|  | 13 +       return trans->id; | 
|  | 14 +} | 
|  | 15 + | 
|  | 16  std::ostream &GotoCodeGen::TO_STATE_ACTION_SWITCH() | 
|  | 17  { | 
|  | 18         /* Walk the list of functions, printing the cases. */ | 
|  | 19 @@ -109,6 +114,86 @@ | 
|  | 20  } | 
|  | 21 | 
|  | 22 | 
|  | 23 +void GotoCodeGen::emitTableSwitch( RedStateAp *state ) | 
|  | 24 +{ | 
|  | 25 +       /* Load up the singles. */ | 
|  | 26 +       int numSingles = state->outSingle.length(); | 
|  | 27 +       RedTransEl *sdata = state->outSingle.data; | 
|  | 28 + | 
|  | 29 +       /* Load up the ranges.  */ | 
|  | 30 +       int numRanges = state->outRange.length(); | 
|  | 31 +       RedTransEl *rdata = state->outRange.data; | 
|  | 32 + | 
|  | 33 +       int minId = INT_MAX; | 
|  | 34 +       int maxId = INT_MIN; | 
|  | 35 + | 
|  | 36 +       for ( Key i = keyOps->minKey; i <= keyOps->maxKey; i.increment() ) { | 
|  | 37 +               RedTransAp *trans = state->defTrans; | 
|  | 38 +               for ( int j = 0; j < numRanges; j++ ) | 
|  | 39 +                       if ( ( rdata[j].lowKey.getVal() <= i ) && ( i <= rdata[j
     ].highKey.getVal() ) ) | 
|  | 40 +                               trans = rdata[j].value; | 
|  | 41 +               for ( int j = 0; j < numSingles; j++ ) | 
|  | 42 +                       if ( i == sdata[j].lowKey.getVal() ) | 
|  | 43 +                               trans = sdata[j].value; | 
|  | 44 +               if ( minId > TRANS_NR(trans) ) | 
|  | 45 +                       minId = TRANS_NR(trans); | 
|  | 46 +               if ( maxId < TRANS_NR(trans) ) | 
|  | 47 +                       maxId = TRANS_NR(trans); | 
|  | 48 +       } | 
|  | 49 + | 
|  | 50 +       if ( (maxId - minId) <= UCHAR_MAX ) | 
|  | 51 +               out << "\t{\n" << | 
|  | 52 +                       "\t\tstatic const unsigned char jump_table[] = "; | 
|  | 53 +       else if ( (maxId - minId) <= USHRT_MAX ) | 
|  | 54 +               out << "\t{\n" << | 
|  | 55 +                       "\t\tstatic const unsigned short jump_table[] = "; | 
|  | 56 +       else | 
|  | 57 +               out << "\t{\n" << | 
|  | 58 +                       "\t\tstatic const int jump_table[] = "; | 
|  | 59 + | 
|  | 60 +       char delimiter = '{'; | 
|  | 61 +       for ( Key i = keyOps->minKey; i <= keyOps->maxKey; i.increment() ) { | 
|  | 62 +               RedTransAp *trans = state->defTrans; | 
|  | 63 +               for ( int j = 0; j < numRanges; j++ ) | 
|  | 64 +                       if ( ( rdata[j].lowKey.getVal() <= i ) && ( i <= rdata[j
     ].highKey.getVal() ) ) | 
|  | 65 +                               trans = rdata[j].value; | 
|  | 66 +               for ( int j = 0; j < numSingles; j++ ) | 
|  | 67 +                       if ( i == sdata[j].lowKey.getVal() ) | 
|  | 68 +                               trans = sdata[j].value; | 
|  | 69 +               if ( minId >= 0 && maxId <= UCHAR_MAX ) | 
|  | 70 +                       out << delimiter << " " << TRANS_NR(trans); | 
|  | 71 +               else if ( (maxId - minId) <= UCHAR_MAX ) | 
|  | 72 +                       out << delimiter << " " << (TRANS_NR(trans) - minId); | 
|  | 73 +               else if ( minId >= 0 && maxId <= USHRT_MAX ) | 
|  | 74 +                       out << delimiter << " " << TRANS_NR(trans); | 
|  | 75 +               else if ( (maxId - minId) <= USHRT_MAX ) | 
|  | 76 +                       out << delimiter << " " << (TRANS_NR(trans) - minId); | 
|  | 77 +               else | 
|  | 78 +                       out << delimiter << " " << TRANS_NR(trans); | 
|  | 79 +               delimiter = ','; | 
|  | 80 +       } | 
|  | 81 +       out << " };\n"; | 
|  | 82 + | 
|  | 83 +       if (keyOps->minKey != 0 ) | 
|  | 84 +               out << "\t\t" << vCS() << " = jump_table[" << GET_WIDE_KEY(state
     ) << "-" << | 
|  | 85 +                       WIDE_KEY(state, keyOps->minKey) << "]"; | 
|  | 86 +       else | 
|  | 87 +               out << "\t\t" << vCS() << " = jump_table[" << GET_WIDE_KEY(state
     ) << "]"; | 
|  | 88 +       if ( minId >= 0 && maxId <= UCHAR_MAX ) | 
|  | 89 +               out << ";\n"; | 
|  | 90 +       else if ( (maxId - minId) <= UCHAR_MAX ) | 
|  | 91 +               out << " + " << minId << ";\n"; | 
|  | 92 +       else if ( minId >= 0 && maxId <= USHRT_MAX ) | 
|  | 93 +               out << ";\n"; | 
|  | 94 +       else if ( (maxId - minId) <= USHRT_MAX ) | 
|  | 95 +               out << " + " << minId << ";\n"; | 
|  | 96 +       else | 
|  | 97 +               out << ";\n"; | 
|  | 98 + | 
|  | 99 +       out << "\t\tgoto _again;\n" | 
|  | 100 +              "\t}\n"; | 
|  | 101 +} | 
|  | 102 + | 
|  | 103  void GotoCodeGen::emitSingleSwitch( RedStateAp *state ) | 
|  | 104  { | 
|  | 105         /* Load up the singles. */ | 
|  | 106 @@ -361,16 +446,24 @@ | 
|  | 107                                 emitCondBSearch( st, 1, 0, st->stateCondVect.len
     gth() - 1 ); | 
|  | 108                         } | 
|  | 109 | 
|  | 110 -                       /* Try singles. */ | 
|  | 111 -                       if ( st->outSingle.length() > 0 ) | 
|  | 112 -                               emitSingleSwitch( st ); | 
|  | 113 - | 
|  | 114 -                       /* Default case is to binary search for the ranges, if t
     hat fails then */ | 
|  | 115 -                       if ( st->outRange.length() > 0 ) | 
|  | 116 -                               emitRangeBSearch( st, 1, 0, st->outRange.length(
     ) - 1 ); | 
|  | 117 +                       if ( (st->outSingle.length() + st->outRange.length() * 2
     ) > maxTransitions) { | 
|  | 118 + | 
|  | 119 +                               emitTableSwitch( st ); | 
|  | 120 + | 
|  | 121 +                       } else { | 
|  | 122 | 
|  | 123 -                       /* Write the default transition. */ | 
|  | 124 -                       TRANS_GOTO( st->defTrans, 1 ) << "\n"; | 
|  | 125 +                               /* Try singles. */ | 
|  | 126 +                               if ( st->outSingle.length() > 0 ) | 
|  | 127 +                                       emitSingleSwitch( st ); | 
|  | 128 + | 
|  | 129 +                               /* Default case is to binary search for the rang
     es, if that fails then */ | 
|  | 130 +                               if ( st->outRange.length() > 0 ) | 
|  | 131 +                                       emitRangeBSearch( st, 1, 0, st->outRange
     .length() - 1 ); | 
|  | 132 + | 
|  | 133 +                               /* Write the default transition. */ | 
|  | 134 +                               TRANS_GOTO( st->defTrans, 1 ) << "\n"; | 
|  | 135 + | 
|  | 136 +                       } | 
|  | 137                 } | 
|  | 138         } | 
|  | 139         return out; | 
|  | 140 --- ragel/cdgoto.h | 
|  | 141 +++ ragel/cdgoto.h | 
|  | 142 @@ -74,7 +74,9 @@ | 
|  | 143         void STATE_CONDS( RedStateAp *state, bool genDefault ); | 
|  | 144 | 
|  | 145         virtual std::ostream &TRANS_GOTO( RedTransAp *trans, int level ); | 
|  | 146 +       virtual int TRANS_NR( RedTransAp *trans ); | 
|  | 147 | 
|  | 148 +       void emitTableSwitch( RedStateAp *state ); | 
|  | 149         void emitSingleSwitch( RedStateAp *state ); | 
|  | 150         void emitRangeBSearch( RedStateAp *state, int level, int low, int high )
     ; | 
|  | 151 | 
|  | 152 --- ragel/cdipgoto.cpp  2011-02-11 07:14:43.000000000 +0300 | 
|  | 153 +++ ragel/cdipgoto.cpp  2012-05-13 15:20:11.433272943 +0400 | 
|  | 154 @@ -27,9 +27,20 @@ | 
|  | 155  #include "gendata.h" | 
|  | 156  #include "bstmap.h" | 
|  | 157 | 
|  | 158 +bool IpGotoCodeGen::useTransInAgainLabel() | 
|  | 159 +{ | 
|  | 160 +       for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) | 
|  | 161 +               if ( st == redFsm->errState ) | 
|  | 162 +                       continue; | 
|  | 163 +               else if ( (st->outSingle.length() + st->outRange.length() * 2) >
      maxTransitions) | 
|  | 164 +                       return true; | 
|  | 165 +       return false; | 
|  | 166 +} | 
|  | 167 + | 
|  | 168  bool IpGotoCodeGen::useAgainLabel() | 
|  | 169  { | 
|  | 170 -       return redFsm->anyRegActionRets() || | 
|  | 171 +       return useTransInAgainLabel() || | 
|  | 172 +                       redFsm->anyRegActionRets() || | 
|  | 173                         redFsm->anyRegActionByValControl() || | 
|  | 174                         redFsm->anyRegNextStmt(); | 
|  | 175  } | 
|  | 176 @@ -243,6 +254,18 @@ | 
|  | 177         return out; | 
|  | 178  } | 
|  | 179 | 
|  | 180 +int IpGotoCodeGen::TRANS_NR( RedTransAp *trans ) | 
|  | 181 +{ | 
|  | 182 +       if ( trans->action != 0 ) { | 
|  | 183 +               /* Go to the transition which will go to the state. */ | 
|  | 184 +               return trans->id + redFsm->stateList.length(); | 
|  | 185 +       } | 
|  | 186 +       else { | 
|  | 187 +               /* Go directly to the target state. */ | 
|  | 188 +               return trans->targ->id; | 
|  | 189 +       } | 
|  | 190 +} | 
|  | 191 + | 
|  | 192  std::ostream &IpGotoCodeGen::EXIT_STATES() | 
|  | 193  { | 
|  | 194         for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { | 
|  | 195 @@ -258,6 +281,13 @@ | 
|  | 196  std::ostream &IpGotoCodeGen::AGAIN_CASES() | 
|  | 197  { | 
|  | 198         for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { | 
|  | 199 +               if ( useTransInAgainLabel() ) | 
|  | 200 +                       for ( int it = 0; it < st->numInTrans; it++ ) { | 
|  | 201 +                               RedTransAp *trans = st->inTrans[it]; | 
|  | 202 +                               if ( trans->action != 0 && trans->labelNeeded ) | 
|  | 203 +                                       out << | 
|  | 204 +                                               "\t\tcase " << (trans->id + redF
     sm->stateList.length()) << ": goto tr" << trans->id << ";\n"; | 
|  | 205 +                       } | 
|  | 206                 out << | 
|  | 207                         "               case " << st->id << ": goto st" << st->i
     d << ";\n"; | 
|  | 208         } | 
|  | 209 @@ -409,7 +439,6 @@ | 
|  | 210                         out << | 
|  | 211                                 "       " << P() << " += 1;\n"; | 
|  | 212                 } | 
|  | 213 - | 
|  | 214                 out << "_resume:\n"; | 
|  | 215         } | 
|  | 216 | 
|  | 217 --- ragel/cdipgoto.h | 
|  | 218 +++ ragel/cdipgoto.h | 
|  | 219 @@ -40,6 +40,7 @@ | 
|  | 220 | 
|  | 221         std::ostream &EXIT_STATES(); | 
|  | 222         std::ostream &TRANS_GOTO( RedTransAp *trans, int level ); | 
|  | 223 +       int TRANS_NR( RedTransAp *trans ); | 
|  | 224         std::ostream &FINISH_CASES(); | 
|  | 225         std::ostream &AGAIN_CASES(); | 
|  | 226 | 
|  | 227 @@ -58,6 +59,7 @@ | 
|  | 228         virtual void writeExec(); | 
|  | 229 | 
|  | 230  protected: | 
|  | 231 +       bool useTransInAgainLabel(); | 
|  | 232         bool useAgainLabel(); | 
|  | 233 | 
|  | 234         /* Called from GotoCodeGen::STATE_GOTOS just before writing the gotos fo
     r | 
|  | 235 --- ragel/main.cpp | 
|  | 236 +++ ragel/main.cpp | 
|  | 237 @@ -83,6 +83,8 @@ | 
|  | 238  /* Target language and output style. */ | 
|  | 239  CodeStyle codeStyle = GenTables; | 
|  | 240 | 
|  | 241 +long maxTransitions = LONG_MAX; | 
|  | 242 + | 
|  | 243  int numSplitPartitions = 0; | 
|  | 244  bool noLineDirectives = false; | 
|  | 245 | 
|  | 246 @@ -139,6 +140,7 @@ | 
|  | 247  "   -G1                  Faster goto-driven FSM\n" | 
|  | 248  "code style: (C/D)\n" | 
|  | 249  "   -G2                  Really fast goto-driven FSM\n" | 
|  | 250 +"   -GT2                 Really fast goto-driven FSM with table-driven fallback
     \n" | 
|  | 251  "   -P<N>                N-Way Split really fast goto-driven FSM\n" | 
|  | 252         ; | 
|  | 253 | 
|  | 254 @@ -407,7 +409,10 @@ | 
|  | 255                                         codeStyle = GenFGoto; | 
|  | 256                                 else if ( pc.paramArg[0] == '2' ) | 
|  | 257                                         codeStyle = GenIpGoto; | 
|  | 258 -                               else { | 
|  | 259 +                               else if ( pc.paramArg[0] == 'T' && pc.paramArg[1
     ] == '2' ) { | 
|  | 260 +                                       codeStyle = GenIpGoto; | 
|  | 261 +                                       maxTransitions = 32; | 
|  | 262 +                               } else { | 
|  | 263                                         error() << "-G" << pc.paramArg[0] << | 
|  | 264                                                         " is an invalid argument
     " << endl; | 
|  | 265                                         exit(1); | 
|  | 266 --- ragel/ragel.h | 
|  | 267 +++ ragel/ragel.h | 
|  | 268 @@ -109,6 +109,8 @@ | 
|  | 269  extern int numSplitPartitions; | 
|  | 270  extern bool noLineDirectives; | 
|  | 271 | 
|  | 272 +extern long maxTransitions; | 
|  | 273 + | 
|  | 274  std::ostream &error(); | 
|  | 275 | 
|  | 276  /* Target language and output style. */ | 
| OLD | NEW | 
|---|