StackMachine.java revision 1088:7e62d98d4625
1141104Sharti/* 294589Sobrien * Permission is hereby granted, free of charge, to any person obtaining a copy of 394589Sobrien * this software and associated documentation files (the "Software"), to deal in 45814Sjkh * the Software without restriction, including without limitation the rights to 51590Srgrimes * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 61590Srgrimes * of the Software, and to permit persons to whom the Software is furnished to do 71590Srgrimes * so, subject to the following conditions: 81590Srgrimes * 91590Srgrimes * The above copyright notice and this permission notice shall be included in all 101590Srgrimes * copies or substantial portions of the Software. 111590Srgrimes * 121590Srgrimes * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 131590Srgrimes * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 141590Srgrimes * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 151590Srgrimes * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 161590Srgrimes * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 171590Srgrimes * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 181590Srgrimes * SOFTWARE. 191590Srgrimes */ 201590Srgrimespackage jdk.nashorn.internal.runtime.regexp.joni; 211590Srgrimes 221590Srgrimesimport static jdk.nashorn.internal.runtime.regexp.joni.BitStatus.bsAt; 231590Srgrimesimport java.lang.ref.WeakReference; 241590Srgrimesimport jdk.nashorn.internal.runtime.regexp.joni.constants.StackPopLevel; 251590Srgrimesimport jdk.nashorn.internal.runtime.regexp.joni.constants.StackType; 261590Srgrimes 271590Srgrimesabstract class StackMachine extends Matcher implements StackType { 281590Srgrimes protected static final int INVALID_INDEX = -1; 291590Srgrimes 301590Srgrimes protected StackEntry[]stack; 311590Srgrimes protected int stk; // stkEnd 321590Srgrimes 331590Srgrimes protected final int[]repeatStk; 341590Srgrimes protected final int memStartStk, memEndStk; 351590Srgrimes 361590Srgrimes protected StackMachine(final Regex regex, final char[] chars, final int p , final int end) { 371590Srgrimes super(regex, chars, p, end); 3862833Swsanchez 3962833Swsanchez this.stack = regex.stackNeeded ? fetchStack() : null; 401590Srgrimes final int n = regex.numRepeat + (regex.numMem << 1); 411590Srgrimes this.repeatStk = n > 0 ? new int[n] : null; 4262833Swsanchez 4394587Sobrien memStartStk = regex.numRepeat - 1; 441590Srgrimes memEndStk = memStartStk + regex.numMem; 451590Srgrimes /* for index start from 1, mem_start_stk[1]..mem_start_stk[num_mem] */ 461590Srgrimes /* for index start from 1, mem_end_stk[1]..mem_end_stk[num_mem] */ 471590Srgrimes } 481590Srgrimes 491590Srgrimes private static StackEntry[] allocateStack() { 50144467Sharti final StackEntry[]stack = new StackEntry[Config.INIT_MATCH_STACK_SIZE]; 511590Srgrimes stack[0] = new StackEntry(); 52144467Sharti return stack; 53144467Sharti } 54144467Sharti 55144467Sharti private void doubleStack() { 56144467Sharti final StackEntry[] newStack = new StackEntry[stack.length << 1]; 57144467Sharti System.arraycopy(stack, 0, newStack, 0, stack.length); 58144467Sharti stack = newStack; 591590Srgrimes } 60144467Sharti 61144467Sharti static final ThreadLocal<WeakReference<StackEntry[]>> stacks 62144467Sharti = new ThreadLocal<WeakReference<StackEntry[]>>() { 63144467Sharti @SuppressWarnings("unused") 64144467Sharti @Override 651590Srgrimes protected WeakReference<StackEntry[]> initialValue() { 66144467Sharti return new WeakReference<StackEntry[]>(allocateStack()); 67144467Sharti } 68144467Sharti }; 69144467Sharti 701590Srgrimes @SuppressWarnings("unused") 71144467Sharti private static StackEntry[] fetchStack() { 721590Srgrimes WeakReference<StackEntry[]> ref = stacks.get(); 73144467Sharti StackEntry[] stack = ref.get(); 741590Srgrimes if (stack == null) { 75144467Sharti ref = new WeakReference<StackEntry[]>(stack = allocateStack()); 76144467Sharti stacks.set(ref); 77144467Sharti } 78144467Sharti return stack; 791590Srgrimes } 80144467Sharti 81144467Sharti protected final void init() { 82144467Sharti if (stack != null) { 831590Srgrimes pushEnsured(ALT, regex.codeLength - 1); /* bottom stack */ 84144467Sharti } 85144467Sharti if (repeatStk != null) { 86144467Sharti for (int i=1; i<=regex.numMem; i++) { 871590Srgrimes repeatStk[i + memStartStk] = repeatStk[i + memEndStk] = INVALID_INDEX; 88144467Sharti } 891590Srgrimes } 90144467Sharti } 91146132Sharti 92146132Sharti protected final StackEntry ensure1() { 93146132Sharti if (stk >= stack.length) { 94146132Sharti doubleStack(); 95146132Sharti } 96146132Sharti StackEntry e = stack[stk]; 97146132Sharti if (e == null) { 98146132Sharti stack[stk] = e = new StackEntry(); 99146132Sharti } 100146132Sharti return e; 101146132Sharti } 1021590Srgrimes 1031590Srgrimes protected final void pushType(final int type) { 104144494Sharti ensure1().type = type; 1051590Srgrimes stk++; 106141104Sharti } 1071590Srgrimes 108107447Sru private void push(final int type, final int pat, final int s, final int prev) { 109104475Sphk final StackEntry e = ensure1(); 110107447Sru e.type = type; 1111590Srgrimes e.setStatePCode(pat); 112141104Sharti e.setStatePStr(s); 113146160Sjmallett e.setStatePStrPrev(prev); 11494506Scharnier stk++; 1155814Sjkh } 116144665Sharti 1171590Srgrimes protected final void pushEnsured(final int type, final int pat) { 1185814Sjkh final StackEntry e = stack[stk]; 119141104Sharti e.type = type; 12080381Ssheldonh e.setStatePCode(pat); 12194506Scharnier stk++; 122141104Sharti } 123141104Sharti 124142457Sharti protected final void pushAlt(final int pat, final int s, final int prev) { 125146056Sharti push(ALT, pat, s, prev); 1261590Srgrimes } 127141104Sharti 128141104Sharti protected final void pushPos(final int s, final int prev) { 1291590Srgrimes push(POS, -1 /*NULL_UCHARP*/, s, prev); 130141104Sharti } 131141104Sharti 132146574Sharti protected final void pushPosNot(final int pat, final int s, final int prev) { 133146572Sharti push(POS_NOT, pat, s, prev); 134141104Sharti } 135146056Sharti 136141104Sharti protected final void pushStopBT() { 137141104Sharti pushType(STOP_BT); 138141104Sharti } 1391590Srgrimes 140146057Sharti protected final void pushLookBehindNot(final int pat, final int s, final int sprev) { 141146057Sharti push(LOOK_BEHIND_NOT, pat, s, sprev); 142146057Sharti } 1431590Srgrimes 144146057Sharti protected final void pushRepeat(final int id, final int pat) { 145146057Sharti final StackEntry e = ensure1(); 146146057Sharti e.type = REPEAT; 147146057Sharti e.setRepeatNum(id); 148146057Sharti e.setRepeatPCode(pat); 149146057Sharti e.setRepeatCount(0); 150146057Sharti stk++; 151146057Sharti } 152146057Sharti 153144483Sharti protected final void pushRepeatInc(final int sindex) { 154144483Sharti final StackEntry e = ensure1(); 155144483Sharti e.type = REPEAT_INC; 156144483Sharti e.setSi(sindex); 157144483Sharti stk++; 158144483Sharti } 159144483Sharti 160144483Sharti protected final void pushMemStart(final int mnum, final int s) { 161144483Sharti final StackEntry e = ensure1(); 162144483Sharti e.type = MEM_START; 163144483Sharti e.setMemNum(mnum); 164144483Sharti e.setMemPstr(s); 165144665Sharti e.setMemStart(repeatStk[memStartStk + mnum]); 166144483Sharti e.setMemEnd(repeatStk[memEndStk + mnum]); 167144483Sharti repeatStk[memStartStk + mnum] = stk; 168144483Sharti repeatStk[memEndStk + mnum] = INVALID_INDEX; 169144483Sharti stk++; 170144483Sharti } 171144483Sharti 172144483Sharti protected final void pushMemEnd(final int mnum, final int s) { 173144483Sharti final StackEntry e = ensure1(); 174144483Sharti e.type = MEM_END; 175144483Sharti e.setMemNum(mnum); 176144483Sharti e.setMemPstr(s); 177144483Sharti e.setMemStart(repeatStk[memStartStk + mnum]); 178144483Sharti e.setMemEnd(repeatStk[memEndStk + mnum]); 179144483Sharti repeatStk[memEndStk + mnum] = stk; 180144483Sharti stk++; 181144483Sharti } 182144483Sharti 183144483Sharti protected final void pushMemEndMark(final int mnum) { 184144483Sharti final StackEntry e = ensure1(); 185144483Sharti e.type = MEM_END_MARK; 186144483Sharti e.setMemNum(mnum); 187144483Sharti stk++; 188144483Sharti } 189144483Sharti 190146061Sharti protected final int getMemStart(final int mnum) { 191144483Sharti int level = 0; 192144483Sharti int stkp = stk; 193144483Sharti 194144483Sharti while (stkp > 0) { 195144483Sharti stkp--; 196144483Sharti final StackEntry e = stack[stkp]; 197144483Sharti if ((e.type & MASK_MEM_END_OR_MARK) != 0 && e.getMemNum() == mnum) { 198144483Sharti level++; 199144483Sharti } else if (e.type == MEM_START && e.getMemNum() == mnum) { 200144483Sharti if (level == 0) { 201144483Sharti break; 202144483Sharti } 203144483Sharti level--; 204146061Sharti } 205144483Sharti } 206144483Sharti return stkp; 207144483Sharti } 208144483Sharti 209144483Sharti protected final void pushNullCheckStart(final int cnum, final int s) { 210144483Sharti final StackEntry e = ensure1(); 211144483Sharti e.type = NULL_CHECK_START; 212144483Sharti e.setNullCheckNum(cnum); 213144483Sharti e.setNullCheckPStr(s); 214144483Sharti stk++; 215144483Sharti } 216144483Sharti 217144483Sharti protected final void pushNullCheckEnd(final int cnum) { 218144483Sharti final StackEntry e = ensure1(); 219144483Sharti e.type = NULL_CHECK_END; 220144483Sharti e.setNullCheckNum(cnum); 221144483Sharti stk++; 222144483Sharti } 223144483Sharti 224144483Sharti // stack debug routines here 225144483Sharti // ... 226144483Sharti 227144483Sharti protected final void popOne() { 228144483Sharti stk--; 229144483Sharti } 230144483Sharti 231144483Sharti protected final StackEntry pop() { 232144483Sharti switch (regex.stackPopLevel) { 233144483Sharti case StackPopLevel.FREE: 234144483Sharti return popFree(); 235144483Sharti case StackPopLevel.MEM_START: 236144483Sharti return popMemStart(); 237144483Sharti default: 238144483Sharti return popDefault(); 239144483Sharti } 240144483Sharti } 241144483Sharti 242144483Sharti private StackEntry popFree() { 243144483Sharti while (true) { 244144483Sharti final StackEntry e = stack[--stk]; 245144483Sharti 246144483Sharti if ((e.type & MASK_POP_USED) != 0) { 247144483Sharti return e; 248144483Sharti } 249144483Sharti } 250144494Sharti } 251144494Sharti 252144483Sharti private StackEntry popMemStart() { 253144483Sharti while (true) { 254146061Sharti final StackEntry e = stack[--stk]; 255146061Sharti 256144483Sharti if ((e.type & MASK_POP_USED) != 0) { 257144483Sharti return e; 258144483Sharti } else if (e.type == MEM_START) { 259146061Sharti repeatStk[memStartStk + e.getMemNum()] = e.getMemStart(); 260144483Sharti repeatStk[memEndStk + e.getMemNum()] = e.getMemEnd(); 261144494Sharti } 262144494Sharti } 263144483Sharti } 2648874Srgrimes 2651590Srgrimes private StackEntry popDefault() { 266144467Sharti while (true) { 267144467Sharti final StackEntry e = stack[--stk]; 268144467Sharti 269144467Sharti if ((e.type & MASK_POP_USED) != 0) { 270144467Sharti return e; 2711590Srgrimes } else if (e.type == MEM_START) { 27218730Ssteve repeatStk[memStartStk + e.getMemNum()] = e.getMemStart(); 27318730Ssteve repeatStk[memEndStk + e.getMemNum()] = e.getMemEnd(); 27418730Ssteve } else if (e.type == REPEAT_INC) { 27518730Ssteve //int si = stack[stk + IREPEAT_INC_SI]; 276138232Sharti //stack[si + IREPEAT_COUNT]--; 2771590Srgrimes stack[e.getSi()].decreaseRepeatCount(); 2781590Srgrimes } else if (e.type == MEM_END) { 2791590Srgrimes repeatStk[memStartStk + e.getMemNum()] = e.getMemStart(); 2801590Srgrimes repeatStk[memEndStk + e.getMemNum()] = e.getMemEnd(); 2811590Srgrimes } 2821590Srgrimes } 283144467Sharti } 2841590Srgrimes 2851590Srgrimes protected final void popTilPosNot() { 286144467Sharti while (true) { 287144467Sharti stk--; 288144467Sharti final StackEntry e = stack[stk]; 289144467Sharti 290144467Sharti if (e.type == POS_NOT) { 291144467Sharti break; 2921590Srgrimes } else if (e.type == MEM_START) { 2931590Srgrimes repeatStk[memStartStk + e.getMemNum()] = e.getMemStart(); 294144467Sharti repeatStk[memEndStk + e.getMemNum()] = e.getMemStart(); 295146061Sharti } else if (e.type == REPEAT_INC) { 296144467Sharti //int si = stack[stk + IREPEAT_INC_SI]; 297144467Sharti //stack[si + IREPEAT_COUNT]--; 2981590Srgrimes stack[e.getSi()].decreaseRepeatCount(); 2991590Srgrimes } else if (e.type == MEM_END){ 300146140Sharti repeatStk[memStartStk + e.getMemNum()] = e.getMemStart(); 301146140Sharti repeatStk[memEndStk + e.getMemNum()] = e.getMemStart(); 302146140Sharti } 303146140Sharti } 304146140Sharti } 305144656Sharti 306138916Sharti protected final void popTilLookBehindNot() { 307138916Sharti while (true) { 308144494Sharti stk--; 309138916Sharti final StackEntry e = stack[stk]; 310146061Sharti 3111590Srgrimes if (e.type == LOOK_BEHIND_NOT) { 312137572Sphk break; 313104475Sphk } else if (e.type == MEM_START) { 314104475Sphk repeatStk[memStartStk + e.getMemNum()] = e.getMemStart(); 315104475Sphk repeatStk[memEndStk + e.getMemNum()] = e.getMemEnd(); 316146061Sharti } else if (e.type == REPEAT_INC) { 3171590Srgrimes //int si = stack[stk + IREPEAT_INC_SI]; 3181590Srgrimes //stack[si + IREPEAT_COUNT]--; 3191590Srgrimes stack[e.getSi()].decreaseRepeatCount(); 320146061Sharti } else if (e.type == MEM_END) { 3211590Srgrimes repeatStk[memStartStk + e.getMemNum()] = e.getMemStart(); 322146061Sharti repeatStk[memEndStk + e.getMemNum()] = e.getMemEnd(); 3231590Srgrimes } 3241590Srgrimes } 3251590Srgrimes } 326137202Sharti 327137202Sharti protected final int posEnd() { 328138232Sharti int k = stk; 32918730Ssteve while (true) { 3301590Srgrimes k--; 331137252Sharti final StackEntry e = stack[k]; 332137252Sharti if ((e.type & MASK_TO_VOID_TARGET) != 0) { 333137252Sharti e.type = VOID; 3348874Srgrimes } else if (e.type == POS) { 335138916Sharti e.type = VOID; 336138916Sharti break; 337138916Sharti } 3381590Srgrimes } 339144494Sharti return k; 3401590Srgrimes } 341144656Sharti 342144656Sharti protected final void stopBtEnd() { 343144656Sharti int k = stk; 3441590Srgrimes while (true) { 345137605Sharti k--; 346137605Sharti final StackEntry e = stack[k]; 347137605Sharti 3481590Srgrimes if ((e.type & MASK_TO_VOID_TARGET) != 0) { 34918730Ssteve e.type = VOID; 3501590Srgrimes } else if (e.type == STOP_BT) { 3511590Srgrimes e.type = VOID; 35218730Ssteve break; 3531590Srgrimes } 35418730Ssteve } 3551590Srgrimes } 3561590Srgrimes 3571590Srgrimes // int for consistency with other null check routines 35818730Ssteve protected final int nullCheck(final int id, final int s) { 35918730Ssteve int k = stk; 36018730Ssteve while (true) { 36118730Ssteve k--; 36218730Ssteve final StackEntry e = stack[k]; 36318730Ssteve 364103503Sjmallett if (e.type == NULL_CHECK_START) { 36518730Ssteve if (e.getNullCheckNum() == id) { 366138232Sharti return e.getNullCheckPStr() == s ? 1 : 0; 36718730Ssteve } 36818730Ssteve } 36918730Ssteve } 37018730Ssteve } 37118730Ssteve 37218730Ssteve protected final int nullCheckRec(final int id, final int s) { 37318730Ssteve int level = 0; 374103503Sjmallett int k = stk; 375103503Sjmallett while (true) { 37618730Ssteve k--; 37792921Simp final StackEntry e = stack[k]; 37892921Simp 37992921Simp if (e.type == NULL_CHECK_START) { 38092921Simp if (e.getNullCheckNum() == id) { 38192921Simp if (level == 0) { 382146142Sharti return e.getNullCheckPStr() == s ? 1 : 0; 3831590Srgrimes } 384146132Sharti level--; 385146132Sharti } 386146132Sharti } else if (e.type == NULL_CHECK_END) { 387146155Sharti level++; 388146155Sharti } 389146155Sharti } 390146155Sharti } 391146155Sharti 392146155Sharti protected final int nullCheckMemSt(final int id, final int s) { 393146155Sharti int k = stk; 394146155Sharti int isNull; 395146155Sharti while (true) { 396146155Sharti k--; 397146155Sharti StackEntry e = stack[k]; 398146155Sharti 399146155Sharti if (e.type == NULL_CHECK_START) { 400146155Sharti if (e.getNullCheckNum() == id) { 401146155Sharti if (e.getNullCheckPStr() != s) { 402146155Sharti isNull = 0; 403146155Sharti break; 404146155Sharti } 405146155Sharti int endp; 406146155Sharti isNull = 1; 407146155Sharti while (k < stk) { 408146155Sharti if (e.type == MEM_START) { 409146155Sharti if (e.getMemEnd() == INVALID_INDEX) { 410146155Sharti isNull = 0; 411146155Sharti break; 412146155Sharti } 413146155Sharti if (bsAt(regex.btMemEnd, e.getMemNum())) { 414183465Sache endp = stack[e.getMemEnd()].getMemPStr(); 415183465Sache } else { 416183465Sache endp = e.getMemEnd(); 417183465Sache } 418183465Sache if (stack[e.getMemStart()].getMemPStr() != endp) { 419183465Sache isNull = 0; 420146155Sharti break; 421146155Sharti } else if (endp != s) { 422146155Sharti isNull = -1; /* empty, but position changed */ 423146155Sharti } 424146155Sharti } 425146155Sharti k++; 426146155Sharti e = stack[k]; // !! 427146155Sharti } 428146155Sharti break; 429146155Sharti } 430146155Sharti } 431146155Sharti } 432146155Sharti return isNull; 433146155Sharti } 434146155Sharti 435146155Sharti protected final int nullCheckMemStRec(final int id, final int s) { 436146155Sharti int level = 0; 437146155Sharti int k = stk; 438146155Sharti int isNull; 439146155Sharti while (true) { 440146155Sharti k--; 441146155Sharti StackEntry e = stack[k]; 442146155Sharti 443146155Sharti if (e.type == NULL_CHECK_START) { 444146155Sharti if (e.getNullCheckNum() == id) { 445146155Sharti if (level == 0) { 446146155Sharti if (e.getNullCheckPStr() != s) { 447146155Sharti isNull = 0; 448146155Sharti break; 449146155Sharti } 450146155Sharti int endp; 451146155Sharti isNull = 1; 452146155Sharti while (k < stk) { 453146155Sharti if (e.type == MEM_START) { 454146155Sharti if (e.getMemEnd() == INVALID_INDEX) { 455146155Sharti isNull = 0; 456146155Sharti break; 457146155Sharti } 458146155Sharti if (bsAt(regex.btMemEnd, e.getMemNum())) { 459146155Sharti endp = stack[e.getMemEnd()].getMemPStr(); 460146155Sharti } else { 461146155Sharti endp = e.getMemEnd(); 462146155Sharti } 463146155Sharti if (stack[e.getMemStart()].getMemPStr() != endp) { 464146155Sharti isNull = 0; 465146155Sharti break; 466146155Sharti } else if (endp != s) { 467146155Sharti isNull = -1; /* empty, but position changed */ 468146155Sharti } 469146155Sharti } 470146155Sharti k++; 471146155Sharti e = stack[k]; 472146155Sharti } 473146155Sharti break; 474146155Sharti } 475146155Sharti level--; 476146155Sharti } 477146155Sharti } else if (e.type == NULL_CHECK_END) { 478146155Sharti if (e.getNullCheckNum() == id) { 479146155Sharti level++; 480146144Sharti } 481146144Sharti } 482146144Sharti } 483146144Sharti return isNull; 484146144Sharti } 485144467Sharti 486146144Sharti protected final int getRepeat(final int id) { 487146144Sharti int level = 0; 488146144Sharti int k = stk; 489146144Sharti while (true) { 490146144Sharti k--; 491146144Sharti final StackEntry e = stack[k]; 492146144Sharti 493146144Sharti if (e.type == REPEAT) { 494146144Sharti if (level == 0) { 495146144Sharti if (e.getRepeatNum() == id) { 496146144Sharti return k; 497146144Sharti } 498146144Sharti } 499146144Sharti } else if (e.type == CALL_FRAME) { 500146144Sharti level--; 501146144Sharti } else if (e.type == RETURN) { 502146144Sharti level++; 503146144Sharti } 504146144Sharti } 505146144Sharti } 506146131Sharti 507146130Sharti protected final int sreturn() { 508146130Sharti int level = 0; 509146130Sharti int k = stk; 510146130Sharti while (true) { 511146130Sharti k--; 512146130Sharti final StackEntry e = stack[k]; 513146130Sharti 514146130Sharti if (e.type == CALL_FRAME) { 515146130Sharti if (level == 0) { 516146130Sharti return e.getCallFrameRetAddr(); 517146131Sharti } 518146131Sharti level--; 519146131Sharti } else if (e.type == RETURN) { 520146131Sharti level++; 521146131Sharti } 522146131Sharti } 523146131Sharti } 524146131Sharti} 525146131Sharti