1 /*
   2  * Permission is hereby granted, free of charge, to any person obtaining a copy of
   3  * this software and associated documentation files (the "Software"), to deal in
   4  * the Software without restriction, including without limitation the rights to
   5  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
   6  * of the Software, and to permit persons to whom the Software is furnished to do
   7  * so, subject to the following conditions:
   8  *
   9  * The above copyright notice and this permission notice shall be included in all
  10  * copies or substantial portions of the Software.
  11  *
  12  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  13  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  14  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  15  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  16  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  17  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  18  * SOFTWARE.
  19  */
  20 package jdk.nashorn.internal.runtime.regexp.joni;
  21 
  22 import java.lang.ref.WeakReference;
  23 import jdk.nashorn.internal.runtime.regexp.joni.constants.StackPopLevel;
  24 import jdk.nashorn.internal.runtime.regexp.joni.constants.StackType;
  25 
  26 abstract class StackMachine extends Matcher implements StackType {
  27     protected static final int INVALID_INDEX = -1;
  28 
  29     protected StackEntry[]stack;
  30     protected int stk;  // stkEnd
  31 
  32     protected final int[]repeatStk;
  33     protected final int memStartStk, memEndStk;
  34 
  35     protected StackMachine(final Regex regex, final char[] chars, final int p , final int end) {
  36         super(regex, chars, p, end);
  37 
  38         this.stack = regex.stackNeeded ? fetchStack() : null;
  39         final int n = regex.numRepeat + (regex.numMem << 1);
  40         this.repeatStk = n > 0 ? new int[n] : null;
  41 
  42         memStartStk = regex.numRepeat - 1;
  43         memEndStk   = memStartStk + regex.numMem;
  44         /* for index start from 1, mem_start_stk[1]..mem_start_stk[num_mem] */
  45         /* for index start from 1, mem_end_stk[1]..mem_end_stk[num_mem] */
  46     }
  47 
  48     private static StackEntry[] allocateStack() {
  49         final StackEntry[]stack = new StackEntry[Config.INIT_MATCH_STACK_SIZE];
  50         stack[0] = new StackEntry();
  51         return stack;
  52     }
  53 
  54     private void doubleStack() {
  55         final StackEntry[] newStack = new StackEntry[stack.length << 1];
  56         System.arraycopy(stack, 0, newStack, 0, stack.length);
  57         stack = newStack;
  58     }
  59 
  60     static final ThreadLocal<WeakReference<StackEntry[]>> stacks
  61             = new ThreadLocal<WeakReference<StackEntry[]>>() {
  62         @SuppressWarnings("unused")
  63         @Override
  64         protected WeakReference<StackEntry[]> initialValue() {
  65             return new WeakReference<StackEntry[]>(allocateStack());
  66         }
  67     };
  68 
  69     @SuppressWarnings("unused")
  70     private static StackEntry[] fetchStack() {
  71         WeakReference<StackEntry[]> ref = stacks.get();
  72         StackEntry[] stack = ref.get();
  73         if (stack == null) {
  74             ref = new WeakReference<StackEntry[]>(stack = allocateStack());
  75             stacks.set(ref);
  76         }
  77         return stack;
  78     }
  79 
  80     protected final void init() {
  81         if (stack != null) {
  82             pushEnsured(ALT, regex.codeLength - 1); /* bottom stack */
  83         }
  84         if (repeatStk != null) {
  85             for (int i=1; i<=regex.numMem; i++) {
  86                 repeatStk[i + memStartStk] = repeatStk[i + memEndStk] = INVALID_INDEX;
  87             }
  88         }
  89     }
  90 
  91     protected final StackEntry ensure1() {
  92         if (stk >= stack.length) {
  93             doubleStack();
  94         }
  95         StackEntry e = stack[stk];
  96         if (e == null) {
  97             stack[stk] = e = new StackEntry();
  98         }
  99         return e;
 100     }
 101 
 102     protected final void pushType(final int type) {
 103         ensure1().type = type;
 104         stk++;
 105     }
 106 
 107     private void push(final int type, final int pat, final int s, final int prev) {
 108         final StackEntry e = ensure1();
 109         e.type = type;
 110         e.setStatePCode(pat);
 111         e.setStatePStr(s);
 112         e.setStatePStrPrev(prev);
 113         stk++;
 114     }
 115 
 116     protected final void pushEnsured(final int type, final int pat) {
 117         final StackEntry e = stack[stk];
 118         e.type = type;
 119         e.setStatePCode(pat);
 120         stk++;
 121     }
 122 
 123     protected final void pushAlt(final int pat, final int s, final int prev) {
 124         push(ALT, pat, s, prev);
 125     }
 126 
 127     protected final void pushPos(final int s, final int prev) {
 128         push(POS, -1 /*NULL_UCHARP*/, s, prev);
 129     }
 130 
 131     protected final void pushPosNot(final int pat, final int s, final int prev) {
 132         push(POS_NOT, pat, s, prev);
 133     }
 134 
 135     protected final void pushStopBT() {
 136         pushType(STOP_BT);
 137     }
 138 
 139     protected final void pushLookBehindNot(final int pat, final int s, final int sprev) {
 140         push(LOOK_BEHIND_NOT, pat, s, sprev);
 141     }
 142 
 143     protected final void pushRepeat(final int id, final int pat) {
 144         final StackEntry e = ensure1();
 145         e.type = REPEAT;
 146         e.setRepeatNum(id);
 147         e.setRepeatPCode(pat);
 148         e.setRepeatCount(0);
 149         stk++;
 150     }
 151 
 152     protected final void pushRepeatInc(final int sindex) {
 153         final StackEntry e = ensure1();
 154         e.type = REPEAT_INC;
 155         e.setSi(sindex);
 156         stk++;
 157     }
 158 
 159     protected final void pushMemStart(final int mnum, final int s) {
 160         final StackEntry e = ensure1();
 161         e.type = MEM_START;
 162         e.setMemNum(mnum);
 163         e.setMemPstr(s);
 164         e.setMemStart(repeatStk[memStartStk + mnum]);
 165         e.setMemEnd(repeatStk[memEndStk + mnum]);
 166         repeatStk[memStartStk + mnum] = stk;
 167         repeatStk[memEndStk + mnum] = INVALID_INDEX;
 168         stk++;
 169     }
 170 
 171     protected final void pushMemEnd(final int mnum, final int s) {
 172         final StackEntry e = ensure1();
 173         e.type = MEM_END;
 174         e.setMemNum(mnum);
 175         e.setMemPstr(s);
 176         e.setMemStart(repeatStk[memStartStk + mnum]);
 177         e.setMemEnd(repeatStk[memEndStk + mnum]);
 178         repeatStk[memEndStk + mnum] = stk;
 179         stk++;
 180     }
 181 
 182     protected final void pushMemEndMark(final int mnum) {
 183         final StackEntry e = ensure1();
 184         e.type = MEM_END_MARK;
 185         e.setMemNum(mnum);
 186         stk++;
 187     }
 188 
 189     protected final int getMemStart(final int mnum) {
 190         int level = 0;
 191         int stkp = stk;
 192 
 193         while (stkp > 0) {
 194             stkp--;
 195             final StackEntry e = stack[stkp];
 196             if ((e.type & MASK_MEM_END_OR_MARK) != 0 && e.getMemNum() == mnum) {
 197                 level++;
 198             } else if (e.type == MEM_START && e.getMemNum() == mnum) {
 199                 if (level == 0) {
 200                     break;
 201                 }
 202                 level--;
 203             }
 204         }
 205         return stkp;
 206     }
 207 
 208     protected final void pushNullCheckStart(final int cnum, final int s) {
 209         final StackEntry e = ensure1();
 210         e.type = NULL_CHECK_START;
 211         e.setNullCheckNum(cnum);
 212         e.setNullCheckPStr(s);
 213         stk++;
 214     }
 215 
 216     protected final void pushNullCheckEnd(final int cnum) {
 217         final StackEntry e = ensure1();
 218         e.type = NULL_CHECK_END;
 219         e.setNullCheckNum(cnum);
 220         stk++;
 221     }
 222 
 223     // stack debug routines here
 224     // ...
 225 
 226     protected final void popOne() {
 227         stk--;
 228     }
 229 
 230     protected final StackEntry pop() {
 231         switch (regex.stackPopLevel) {
 232         case StackPopLevel.FREE:
 233             return popFree();
 234         case StackPopLevel.MEM_START:
 235             return popMemStart();
 236         default:
 237             return popDefault();
 238         }
 239     }
 240 
 241     private StackEntry popFree() {
 242         while (true) {
 243             final StackEntry e = stack[--stk];
 244 
 245             if ((e.type & MASK_POP_USED) != 0) {
 246                 return e;
 247             }
 248         }
 249     }
 250 
 251     private StackEntry popMemStart() {
 252         while (true) {
 253             final StackEntry e = stack[--stk];
 254 
 255             if ((e.type & MASK_POP_USED) != 0) {
 256                 return e;
 257             } else if (e.type == MEM_START) {
 258                 repeatStk[memStartStk + e.getMemNum()] = e.getMemStart();
 259                 repeatStk[memEndStk + e.getMemNum()] = e.getMemEnd();
 260             }
 261         }
 262     }
 263 
 264     private StackEntry popDefault() {
 265         while (true) {
 266             final StackEntry e = stack[--stk];
 267 
 268             if ((e.type & MASK_POP_USED) != 0) {
 269                 return e;
 270             } else if (e.type == MEM_START) {
 271                 repeatStk[memStartStk + e.getMemNum()] = e.getMemStart();
 272                 repeatStk[memEndStk + e.getMemNum()] = e.getMemEnd();
 273             } else if (e.type == REPEAT_INC) {
 274                 //int si = stack[stk + IREPEAT_INC_SI];
 275                 //stack[si + IREPEAT_COUNT]--;
 276                 stack[e.getSi()].decreaseRepeatCount();
 277             } else if (e.type == MEM_END) {
 278                 repeatStk[memStartStk + e.getMemNum()] = e.getMemStart();
 279                 repeatStk[memEndStk + e.getMemNum()] = e.getMemEnd();
 280             }
 281         }
 282     }
 283 
 284     protected final void popTilPosNot() {
 285         while (true) {
 286             stk--;
 287             final StackEntry e = stack[stk];
 288 
 289             if (e.type == POS_NOT) {
 290                 break;
 291             } else if (e.type == MEM_START) {
 292                 repeatStk[memStartStk + e.getMemNum()] = e.getMemStart();
 293                 repeatStk[memEndStk + e.getMemNum()] = e.getMemStart();
 294             } else if (e.type == REPEAT_INC) {
 295                 //int si = stack[stk + IREPEAT_INC_SI];
 296                 //stack[si + IREPEAT_COUNT]--;
 297                 stack[e.getSi()].decreaseRepeatCount();
 298             } else if (e.type == MEM_END){
 299                 repeatStk[memStartStk + e.getMemNum()] = e.getMemStart();
 300                 repeatStk[memEndStk + e.getMemNum()] = e.getMemStart();
 301             }
 302         }
 303     }
 304 
 305     protected final void popTilLookBehindNot() {
 306         while (true) {
 307             stk--;
 308             final StackEntry e = stack[stk];
 309 
 310             if (e.type == LOOK_BEHIND_NOT) {
 311                 break;
 312             } else if (e.type == MEM_START) {
 313                 repeatStk[memStartStk + e.getMemNum()] = e.getMemStart();
 314                 repeatStk[memEndStk + e.getMemNum()] = e.getMemEnd();
 315             } else if (e.type == REPEAT_INC) {
 316                 //int si = stack[stk + IREPEAT_INC_SI];
 317                 //stack[si + IREPEAT_COUNT]--;
 318                 stack[e.getSi()].decreaseRepeatCount();
 319             } else if (e.type == MEM_END) {
 320                 repeatStk[memStartStk + e.getMemNum()] = e.getMemStart();
 321                 repeatStk[memEndStk + e.getMemNum()] = e.getMemEnd();
 322             }
 323         }
 324     }
 325 
 326     protected final int posEnd() {
 327         int k = stk;
 328         while (true) {
 329             k--;
 330             final StackEntry e = stack[k];
 331             if ((e.type & MASK_TO_VOID_TARGET) != 0) {
 332                 e.type = VOID;
 333             } else if (e.type == POS) {
 334                 e.type = VOID;
 335                 break;
 336             }
 337         }
 338         return k;
 339     }
 340 
 341     protected final void stopBtEnd() {
 342         int k = stk;
 343         while (true) {
 344             k--;
 345             final StackEntry e = stack[k];
 346 
 347             if ((e.type & MASK_TO_VOID_TARGET) != 0) {
 348                 e.type = VOID;
 349             } else if (e.type == STOP_BT) {
 350                 e.type = VOID;
 351                 break;
 352             }
 353         }
 354     }
 355 
 356     // int for consistency with other null check routines
 357     protected final int nullCheck(final int id, final int s) {
 358         int k = stk;
 359         while (true) {
 360             k--;
 361             final StackEntry e = stack[k];
 362 
 363             if (e.type == NULL_CHECK_START) {
 364                 if (e.getNullCheckNum() == id) {
 365                     return e.getNullCheckPStr() == s ? 1 : 0;
 366                 }
 367             }
 368         }
 369     }
 370 
 371     protected final int nullCheckMemSt(final int id, final int s) {
 372         // Return -1 here to cause operation to fail
 373         return -nullCheck(id, s);
 374     }
 375 
 376     protected final int getRepeat(final int id) {
 377         int level = 0;
 378         int k = stk;
 379         while (true) {
 380             k--;
 381             final StackEntry e = stack[k];
 382 
 383             if (e.type == REPEAT) {
 384                 if (level == 0) {
 385                     if (e.getRepeatNum() == id) {
 386                         return k;
 387                     }
 388                 }
 389             } else if (e.type == CALL_FRAME) {
 390                 level--;
 391             } else if (e.type == RETURN) {
 392                 level++;
 393             }
 394         }
 395     }
 396 
 397     protected final int sreturn() {
 398         int level = 0;
 399         int k = stk;
 400         while (true) {
 401             k--;
 402             final StackEntry e = stack[k];
 403 
 404             if (e.type == CALL_FRAME) {
 405                 if (level == 0) {
 406                     return e.getCallFrameRetAddr();
 407                 }
 408                 level--;
 409             } else if (e.type == RETURN) {
 410                 level++;
 411             }
 412         }
 413     }
 414 }