ByteCodePrinter.java revision 953:221a84ef44c0
150472Speter/*
27130Srgrimes * Permission is hereby granted, free of charge, to any person obtaining a copy of
378822Snik * this software and associated documentation files (the "Software"), to deal in
450203Srgrimes * the Software without restriction, including without limitation the rights to
57130Srgrimes * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
639161Sobrien * of the Software, and to permit persons to whom the Software is furnished to do
78571Srgrimes * so, subject to the following conditions:
88571Srgrimes *
97130Srgrimes * The above copyright notice and this permission notice shall be included in all
10122402Sharti * copies or substantial portions of the Software.
11122402Sharti *
12123051Sru * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
13123051Sru * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14123051Sru * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
15123051Sru * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
16123051Sru * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17123051Sru * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
18123051Sru * SOFTWARE.
19123051Sru */
20123051Srupackage jdk.nashorn.internal.runtime.regexp.joni;
21123051Sru
2239250Sgibbsimport jdk.nashorn.internal.runtime.regexp.joni.ast.CClassNode;
2339250Sgibbsimport jdk.nashorn.internal.runtime.regexp.joni.constants.Arguments;
2439250Sgibbsimport jdk.nashorn.internal.runtime.regexp.joni.constants.OPCode;
2539250Sgibbsimport jdk.nashorn.internal.runtime.regexp.joni.constants.OPSize;
26104489Ssamimport jdk.nashorn.internal.runtime.regexp.joni.exception.InternalException;
27104489Ssam
2856583Sn_hibmaclass ByteCodePrinter {
2988748Sambrisko    final int[] code;
3088748Sambrisko    final int codeLength;
31123288Sobrien    final char[][] templates;
32123288Sobrien
33123051Sru    Object[] operands;
34123051Sru
3577756Sru    private final static String OpCodeNames[] = new String[] {
3677756Sru            "finish", /*OP_FINISH*/
37103627Struckman            "end", /*OP_END*/
38103627Struckman            "exact1", /*OP_EXACT1*/
39105400Stmm            "exact2", /*OP_EXACT2*/
40105400Stmm            "exact3", /*OP_EXACT3*/
4160724Speter            "exact4", /*OP_EXACT4*/
4260724Speter            "exact5", /*OP_EXACT5*/
43103627Struckman            "exactn", /*OP_EXACTN*/
44103627Struckman            "exactmb2-n1", /*OP_EXACTMB2N1*/
4556583Sn_hibma            "exactmb2-n2", /*OP_EXACTMB2N2*/
4656583Sn_hibma            "exactmb2-n3", /*OP_EXACTMB2N3*/
47116258Sharti            "exactmb2-n", /*OP_EXACTMB2N*/
48116258Sharti            "exactmb3n", /*OP_EXACTMB3N*/
4970811Speter            "exactmbn", /*OP_EXACTMBN*/
5070811Speter            "exact1-ic", /*OP_EXACT1_IC*/
5156583Sn_hibma            "exactn-ic", /*OP_EXACTN_IC*/
5275415Sbp            "cclass", /*OP_CCLASS*/
5388050Sgreen            "cclass-mb", /*OP_CCLASS_MB*/
5488050Sgreen            "cclass-mix", /*OP_CCLASS_MIX*/
5577031Sru            "cclass-not", /*OP_CCLASS_NOT*/
5677031Sru            "cclass-mb-not", /*OP_CCLASS_MB_NOT*/
5777031Sru            "cclass-mix-not", /*OP_CCLASS_MIX_NOT*/
5877031Sru            "cclass-node", /*OP_CCLASS_NODE*/
5977162Sru            "anychar", /*OP_ANYCHAR*/
6077162Sru            "anychar-ml", /*OP_ANYCHAR_ML*/
6177223Sru            "anychar*", /*OP_ANYCHAR_STAR*/
6277223Sru            "anychar-ml*", /*OP_ANYCHAR_ML_STAR*/
6377031Sru            "anychar*-peek-next", /*OP_ANYCHAR_STAR_PEEK_NEXT*/
6477031Sru            "anychar-ml*-peek-next", /*OP_ANYCHAR_ML_STAR_PEEK_NEXT*/
6577223Sru            "word", /*OP_WORD*/
6677223Sru            "not-word", /*OP_NOT_WORD*/
6777031Sru            "word-bound", /*OP_WORD_BOUND*/
6877031Sru            "not-word-bound", /*OP_NOT_WORD_BOUND*/
6977031Sru            "word-begin", /*OP_WORD_BEGIN*/
7077031Sru            "word-end", /*OP_WORD_END*/
7175461Sru            "begin-buf", /*OP_BEGIN_BUF*/
7275461Sru            "end-buf", /*OP_END_BUF*/
73123051Sru            "begin-line", /*OP_BEGIN_LINE*/
74123051Sru            "end-line", /*OP_END_LINE*/
7577031Sru            "semi-end-buf", /*OP_SEMI_END_BUF*/
7677031Sru            "begin-position", /*OP_BEGIN_POSITION*/
7777031Sru            "backref1", /*OP_BACKREF1*/
7877031Sru            "backref2", /*OP_BACKREF2*/
7975415Sbp            "backrefn", /*OP_BACKREFN*/
80110542Sphk            "backrefn-ic", /*OP_BACKREFN_IC*/
81128768Spjd            "backref_multi", /*OP_BACKREF_MULTI*/
82128768Spjd            "backref_multi-ic", /*OP_BACKREF_MULTI_IC*/
83128768Spjd            "backref_at_level", /*OP_BACKREF_AT_LEVEL*/
84128768Spjd            "mem-start", /*OP_MEMORY_START*/
85129476Spjd            "mem-start-push", /*OP_MEMORY_START_PUSH*/
86129476Spjd            "mem-end-push", /*OP_MEMORY_END_PUSH*/
87129476Spjd            "mem-end-push-rec", /*OP_MEMORY_END_PUSH_REC*/
88129476Spjd            "mem-end", /*OP_MEMORY_END*/
89110542Sphk            "mem-end-rec", /*OP_MEMORY_END_REC*/
90125892Sache            "fail", /*OP_FAIL*/
91126214Sache            "jump", /*OP_JUMP*/
92126214Sache            "push", /*OP_PUSH*/
93125892Sache            "pop", /*OP_POP*/
9467523Sarchie            "push-or-jump-e1", /*OP_PUSH_OR_JUMP_EXACT1*/
9567523Sarchie            "push-if-peek-next", /*OP_PUSH_IF_PEEK_NEXT*/
9626453Sache            "repeat", /*OP_REPEAT*/
9726453Sache            "repeat-ng", /*OP_REPEAT_NG*/
9826453Sache            "repeat-inc", /*OP_REPEAT_INC*/
9926453Sache            "repeat-inc-ng", /*OP_REPEAT_INC_NG*/
100120950Snectar            "repeat-inc-sg", /*OP_REPEAT_INC_SG*/
101120950Snectar            "repeat-inc-ng-sg", /*OP_REPEAT_INC_NG_SG*/
10290804Sgshapiro            "null-check-start", /*OP_NULL_CHECK_START*/
10390804Sgshapiro            "null-check-end", /*OP_NULL_CHECK_END*/
10426453Sache            "null-check-end-memst", /*OP_NULL_CHECK_END_MEMST*/
10593229Sru            "null-check-end-memst-push", /*OP_NULL_CHECK_END_MEMST_PUSH*/
10693229Sru            "push-pos", /*OP_PUSH_POS*/
10726453Sache            "pop-pos", /*OP_POP_POS*/
10826453Sache            "push-pos-not", /*OP_PUSH_POS_NOT*/
10926453Sache            "fail-pos", /*OP_FAIL_POS*/
110116818Ssam            "push-stop-bt", /*OP_PUSH_STOP_BT*/
111116818Ssam            "pop-stop-bt", /*OP_POP_STOP_BT*/
11226453Sache            "look-behind", /*OP_LOOK_BEHIND*/
11326453Sache            "push-look-behind-not", /*OP_PUSH_LOOK_BEHIND_NOT*/
11439271Sphk            "fail-look-behind-not", /*OP_FAIL_LOOK_BEHIND_NOT*/
11593229Sru            "call", /*OP_CALL*/
11693229Sru            "return", /*OP_RETURN*/
11793229Sru            "state-check-push", /*OP_STATE_CHECK_PUSH*/
11893229Sru            "state-check-push-or-jump", /*OP_STATE_CHECK_PUSH_OR_JUMP*/
11993229Sru            "state-check", /*OP_STATE_CHECK*/
12093229Sru            "state-check-anychar*", /*OP_STATE_CHECK_ANYCHAR_STAR*/
12193229Sru            "state-check-anychar-ml*", /*OP_STATE_CHECK_ANYCHAR_ML_STAR*/
12293229Sru            "set-option-push", /*OP_SET_OPTION_PUSH*/
12339271Sphk            "set-option", /*OP_SET_OPTION*/
12452419Sjulian    };
125116811Sharti
126116811Sharti    private final static int OpCodeArgTypes[] = new int[] {
127107123Sjulian            Arguments.NON, /*OP_FINISH*/
128107123Sjulian            Arguments.NON, /*OP_END*/
129107123Sjulian            Arguments.SPECIAL, /*OP_EXACT1*/
130107123Sjulian            Arguments.SPECIAL, /*OP_EXACT2*/
13152419Sjulian            Arguments.SPECIAL, /*OP_EXACT3*/
13226453Sache            Arguments.SPECIAL, /*OP_EXACT4*/
13326453Sache            Arguments.SPECIAL, /*OP_EXACT5*/
13452905Sjlemon            Arguments.SPECIAL, /*OP_EXACTN*/
13552905Sjlemon            Arguments.SPECIAL, /*OP_EXACTMB2N1*/
136105376Ssam            Arguments.SPECIAL, /*OP_EXACTMB2N2*/
137105376Ssam            Arguments.SPECIAL, /*OP_EXACTMB2N3*/
13826453Sache            Arguments.SPECIAL, /*OP_EXACTMB2N*/
13926453Sache            Arguments.SPECIAL, /*OP_EXACTMB3N*/
14026453Sache            Arguments.SPECIAL, /*OP_EXACTMBN*/
14126453Sache            Arguments.SPECIAL, /*OP_EXACT1_IC*/
14267128Sbrian            Arguments.SPECIAL, /*OP_EXACTN_IC*/
143121949Sharti            Arguments.SPECIAL, /*OP_CCLASS*/
144121949Sharti            Arguments.SPECIAL, /*OP_CCLASS_MB*/
145121337Sharti            Arguments.SPECIAL, /*OP_CCLASS_MIX*/
146121337Sharti            Arguments.SPECIAL, /*OP_CCLASS_NOT*/
147122211Sharti            Arguments.SPECIAL, /*OP_CCLASS_MB_NOT*/
148122211Sharti            Arguments.SPECIAL, /*OP_CCLASS_MIX_NOT*/
14967128Sbrian            Arguments.SPECIAL, /*OP_CCLASS_NODE*/
15052228Sbp            Arguments.NON, /*OP_ANYCHAR*/
15152228Sbp            Arguments.NON, /*OP_ANYCHAR_ML*/
15275375Sbp            Arguments.NON, /*OP_ANYCHAR_STAR*/
15375375Sbp            Arguments.NON, /*OP_ANYCHAR_ML_STAR*/
15426453Sache            Arguments.SPECIAL, /*OP_ANYCHAR_STAR_PEEK_NEXT*/
15526453Sache            Arguments.SPECIAL, /*OP_ANYCHAR_ML_STAR_PEEK_NEXT*/
15683653Speter            Arguments.NON, /*OP_WORD*/
15783653Speter            Arguments.NON, /*OP_NOT_WORD*/
15883653Speter            Arguments.NON, /*OP_WORD_BOUND*/
15983653Speter            Arguments.NON, /*OP_NOT_WORD_BOUND*/
1608571Srgrimes            Arguments.NON, /*OP_WORD_BEGIN*/
1617130Srgrimes            Arguments.NON, /*OP_WORD_END*/
16255097Skris            Arguments.NON, /*OP_BEGIN_BUF*/
16355097Skris            Arguments.NON, /*OP_END_BUF*/
16426453Sache            Arguments.NON, /*OP_BEGIN_LINE*/
16526453Sache            Arguments.NON, /*OP_END_LINE*/
16634030Sdufault            Arguments.NON, /*OP_SEMI_END_BUF*/
16734030Sdufault            Arguments.NON, /*OP_BEGIN_POSITION*/
1688571Srgrimes            Arguments.NON, /*OP_BACKREF1*/
1697130Srgrimes            Arguments.NON, /*OP_BACKREF2*/
1708571Srgrimes            Arguments.MEMNUM, /*OP_BACKREFN*/
1717130Srgrimes            Arguments.SPECIAL, /*OP_BACKREFN_IC*/
1728571Srgrimes            Arguments.SPECIAL, /*OP_BACKREF_MULTI*/
1737130Srgrimes            Arguments.SPECIAL, /*OP_BACKREF_MULTI_IC*/
1748571Srgrimes            Arguments.SPECIAL, /*OP_BACKREF_AT_LEVEL*/
1757130Srgrimes            Arguments.MEMNUM, /*OP_MEMORY_START*/
17641230Sjdp            Arguments.MEMNUM, /*OP_MEMORY_START_PUSH*/
177101192Srwatson            Arguments.MEMNUM, /*OP_MEMORY_END_PUSH*/
178101192Srwatson            Arguments.MEMNUM, /*OP_MEMORY_END_PUSH_REC*/
179101192Srwatson            Arguments.MEMNUM, /*OP_MEMORY_END*/
180101192Srwatson            Arguments.MEMNUM, /*OP_MEMORY_END_REC*/
181107547Srwatson            Arguments.NON, /*OP_FAIL*/
182107547Srwatson            Arguments.RELADDR, /*OP_JUMP*/
183101192Srwatson            Arguments.RELADDR, /*OP_PUSH*/
184101192Srwatson            Arguments.NON, /*OP_POP*/
185105875Srwatson            Arguments.SPECIAL, /*OP_PUSH_OR_JUMP_EXACT1*/
186105875Srwatson            Arguments.SPECIAL, /*OP_PUSH_IF_PEEK_NEXT*/
18741230Sjdp            Arguments.SPECIAL, /*OP_REPEAT*/
18826453Sache            Arguments.SPECIAL, /*OP_REPEAT_NG*/
18926453Sache            Arguments.MEMNUM, /*OP_REPEAT_INC*/
19026453Sache            Arguments.MEMNUM, /*OP_REPEAT_INC_NG*/
19126453Sache            Arguments.MEMNUM, /*OP_REPEAT_INC_SG*/
19226453Sache            Arguments.MEMNUM, /*OP_REPEAT_INC_NG_SG*/
19326453Sache            Arguments.MEMNUM, /*OP_NULL_CHECK_START*/
19426453Sache            Arguments.MEMNUM, /*OP_NULL_CHECK_END*/
19526453Sache            Arguments.MEMNUM, /*OP_NULL_CHECK_END_MEMST*/
19626453Sache            Arguments.MEMNUM, /*OP_NULL_CHECK_END_MEMST_PUSH*/
19726453Sache            Arguments.NON, /*OP_PUSH_POS*/
1987130Srgrimes            Arguments.NON, /*OP_POP_POS*/
199            Arguments.RELADDR, /*OP_PUSH_POS_NOT*/
200            Arguments.NON, /*OP_FAIL_POS*/
201            Arguments.NON, /*OP_PUSH_STOP_BT*/
202            Arguments.NON, /*OP_POP_STOP_BT*/
203            Arguments.SPECIAL, /*OP_LOOK_BEHIND*/
204            Arguments.SPECIAL, /*OP_PUSH_LOOK_BEHIND_NOT*/
205            Arguments.NON, /*OP_FAIL_LOOK_BEHIND_NOT*/
206            Arguments.ABSADDR, /*OP_CALL*/
207            Arguments.NON, /*OP_RETURN*/
208            Arguments.SPECIAL, /*OP_STATE_CHECK_PUSH*/
209            Arguments.SPECIAL, /*OP_STATE_CHECK_PUSH_OR_JUMP*/
210            Arguments.STATE_CHECK, /*OP_STATE_CHECK*/
211            Arguments.STATE_CHECK, /*OP_STATE_CHECK_ANYCHAR_STAR*/
212            Arguments.STATE_CHECK, /*OP_STATE_CHECK_ANYCHAR_ML_STAR*/
213            Arguments.OPTION, /*OP_SET_OPTION_PUSH*/
214            Arguments.OPTION, /*OP_SET_OPTION*/
215    };
216
217    public ByteCodePrinter(final Regex regex) {
218        code = regex.code;
219        codeLength = regex.codeLength;
220        operands = regex.operands;
221
222        templates = regex.templates;
223    }
224
225    public String byteCodeListToString() {
226        return compiledByteCodeListToString();
227    }
228
229    private void pString(final StringBuilder sb, final int len, final int s) {
230        sb.append(":");
231        sb.append(new String(code, s, len));
232    }
233
234    private void pLenString(final StringBuilder sb, final int len, final int s) {
235        sb.append(":").append(len).append(":");
236        sb.append(new String(code, s, len));
237    }
238
239    private void pLenStringFromTemplate(final StringBuilder sb, final int len, final char[] tm, final int idx) {
240        sb.append(":T:").append(len).append(":");
241        sb.append(tm, idx, len);
242    }
243
244    public int compiledByteCodeToString(final StringBuilder sb, int bp) {
245        int len, n, mem, addr, scn, cod;
246        BitSet bs;
247        CClassNode cc;
248        int tm, idx;
249
250        sb.append("[").append(OpCodeNames[code[bp]]);
251        final int argType = OpCodeArgTypes[code[bp]];
252        final int ip = bp;
253        if (argType != Arguments.SPECIAL) {
254            bp++;
255            switch (argType) {
256            case Arguments.NON:
257                break;
258
259            case Arguments.RELADDR:
260                sb.append(":(").append(code[bp]).append(")");
261                bp += OPSize.RELADDR;
262                break;
263
264            case Arguments.ABSADDR:
265                sb.append(":(").append(code[bp]).append(")");
266                bp += OPSize.ABSADDR;
267                break;
268
269            case Arguments.LENGTH:
270                sb.append(":").append(code[bp]);
271                bp += OPSize.LENGTH;
272                break;
273
274            case Arguments.MEMNUM:
275                sb.append(":").append(code[bp]);
276                bp += OPSize.MEMNUM;
277                break;
278
279            case Arguments.OPTION:
280                sb.append(":").append(code[bp]);
281                bp += OPSize.OPTION;
282                break;
283
284            case Arguments.STATE_CHECK:
285                sb.append(":").append(code[bp]);
286                bp += OPSize.STATE_CHECK;
287                break;
288            }
289        } else {
290            switch (code[bp++]) {
291            case OPCode.EXACT1:
292            case OPCode.ANYCHAR_STAR_PEEK_NEXT:
293            case OPCode.ANYCHAR_ML_STAR_PEEK_NEXT:
294                pString(sb, 1, bp++);
295                break;
296
297            case OPCode.EXACT2:
298                pString(sb, 2, bp);
299                bp += 2;
300                break;
301
302            case OPCode.EXACT3:
303                pString(sb, 3, bp);
304                bp += 3;
305                break;
306
307            case OPCode.EXACT4:
308                pString(sb, 4, bp);
309                bp += 4;
310                break;
311
312            case OPCode.EXACT5:
313                pString(sb, 5, bp);
314                bp += 5;
315                break;
316
317            case OPCode.EXACTN:
318                len = code[bp];
319                bp += OPSize.LENGTH;
320                if (Config.USE_STRING_TEMPLATES) {
321                    tm = code[bp];
322                    bp += OPSize.INDEX;
323                    idx = code[bp];
324                    bp += OPSize.INDEX;
325                    pLenStringFromTemplate(sb, len, templates[tm], idx);
326                } else {
327                    pLenString(sb, len, bp);
328                    bp += len;
329                }
330                break;
331
332            case OPCode.EXACT1_IC:
333                pString(sb, 1, bp);
334                bp++;
335                break;
336
337            case OPCode.EXACTN_IC:
338                len = code[bp];
339                bp += OPSize.LENGTH;
340                if (Config.USE_STRING_TEMPLATES) {
341                    tm = code[bp];
342                    bp += OPSize.INDEX;
343                    idx = code[bp];
344                    bp += OPSize.INDEX;
345                    pLenStringFromTemplate(sb, len, templates[tm], idx);
346                } else {
347                    pLenString(sb, len, bp);
348                    bp += len;
349                }
350                break;
351
352            case OPCode.CCLASS:
353                bs = new BitSet();
354                System.arraycopy(code, bp, bs.bits, 0, BitSet.BITSET_SIZE);
355                n = bs.numOn();
356                bp += BitSet.BITSET_SIZE;
357                sb.append(":").append(n);
358                break;
359
360            case OPCode.CCLASS_NOT:
361                bs = new BitSet();
362                System.arraycopy(code, bp, bs.bits, 0, BitSet.BITSET_SIZE);
363                n = bs.numOn();
364                bp += BitSet.BITSET_SIZE;
365                sb.append(":").append(n);
366                break;
367
368            case OPCode.CCLASS_MB:
369            case OPCode.CCLASS_MB_NOT:
370                len = code[bp];
371                bp += OPSize.LENGTH;
372                cod = code[bp];
373                //bp += OPSize.CODE_POINT;
374                bp += len;
375                sb.append(":").append(cod).append(":").append(len);
376                break;
377
378            case OPCode.CCLASS_MIX:
379            case OPCode.CCLASS_MIX_NOT:
380                bs = new BitSet();
381                System.arraycopy(code, bp, bs.bits, 0, BitSet.BITSET_SIZE);
382                n = bs.numOn();
383                bp += BitSet.BITSET_SIZE;
384                len = code[bp];
385                bp += OPSize.LENGTH;
386                cod = code[bp];
387                //bp += OPSize.CODE_POINT;
388                bp += len;
389                sb.append(":").append(n).append(":").append(cod).append(":").append(len);
390                break;
391
392            case OPCode.CCLASS_NODE:
393                cc = (CClassNode)operands[code[bp]];
394                bp += OPSize.POINTER;
395                n = cc.bs.numOn();
396                sb.append(":").append(cc).append(":").append(n);
397                break;
398
399            case OPCode.BACKREFN_IC:
400                mem = code[bp];
401                bp += OPSize.MEMNUM;
402                sb.append(":").append(mem);
403                break;
404
405            case OPCode.BACKREF_MULTI_IC:
406            case OPCode.BACKREF_MULTI:
407                sb.append(" ");
408                len = code[bp];
409                bp += OPSize.LENGTH;
410                for (int i=0; i<len; i++) {
411                    mem = code[bp];
412                    bp += OPSize.MEMNUM;
413                    if (i > 0) sb.append(", ");
414                    sb.append(mem);
415                }
416                break;
417
418            case OPCode.BACKREF_WITH_LEVEL: {
419                final int option = code[bp];
420                bp += OPSize.OPTION;
421                sb.append(":").append(option);
422                final int level = code[bp];
423                bp += OPSize.LENGTH;
424                sb.append(":").append(level);
425                sb.append(" ");
426                len = code[bp];
427                bp += OPSize.LENGTH;
428                for (int i=0; i<len; i++) {
429                    mem = code[bp];
430                    bp += OPSize.MEMNUM;
431                    if (i > 0) sb.append(", ");
432                    sb.append(mem);
433                }
434                break;
435            }
436
437            case OPCode.REPEAT:
438            case OPCode.REPEAT_NG:
439                mem = code[bp];
440                bp += OPSize.MEMNUM;
441                addr = code[bp];
442                bp += OPSize.RELADDR;
443                sb.append(":").append(mem).append(":").append(addr);
444                break;
445
446            case OPCode.PUSH_OR_JUMP_EXACT1:
447            case OPCode.PUSH_IF_PEEK_NEXT:
448                addr = code[bp];
449                bp += OPSize.RELADDR;
450                sb.append(":(").append(addr).append(")");
451                pString(sb, 1, bp);
452                bp++;
453                break;
454
455            case OPCode.LOOK_BEHIND:
456                len = code[bp];
457                bp += OPSize.LENGTH;
458                sb.append(":").append(len);
459                break;
460
461            case OPCode.PUSH_LOOK_BEHIND_NOT:
462                addr = code[bp];
463                bp += OPSize.RELADDR;
464                len = code[bp];
465                bp += OPSize.LENGTH;
466                sb.append(":").append(len).append(":(").append(addr).append(")");
467                break;
468
469            case OPCode.STATE_CHECK_PUSH:
470            case OPCode.STATE_CHECK_PUSH_OR_JUMP:
471                scn = code[bp];
472                bp += OPSize.STATE_CHECK_NUM;
473                addr = code[bp];
474                bp += OPSize.RELADDR;
475                sb.append(":").append(scn).append(":(").append(addr).append(")");
476                break;
477
478            default:
479                throw new InternalException("undefined code: " + code[--bp]);
480            }
481        }
482
483        sb.append("]");
484
485        // @opcode_address(opcode_size)
486        if (Config.DEBUG_COMPILE_BYTE_CODE_INFO) {
487            sb.append("@").append(ip).append("(").append((bp - ip)).append(")");
488        }
489
490        return bp;
491    }
492
493    private String compiledByteCodeListToString() {
494        final StringBuilder sb = new StringBuilder();
495        sb.append("code length: ").append(codeLength).append("\n");
496
497        int ncode = 0;
498        int bp = 0;
499        final int end = codeLength;
500
501        while (bp < end) {
502            ncode++;
503
504            if (bp > 0) sb.append(ncode % 5 == 0 ? "\n" : " ");
505
506            bp = compiledByteCodeToString(sb, bp);
507        }
508        sb.append("\n");
509        return sb.toString();
510    }
511}
512