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 jdk.nashorn.internal.runtime.regexp.joni.ast.CClassNode; 23 import jdk.nashorn.internal.runtime.regexp.joni.constants.Arguments; 24 import jdk.nashorn.internal.runtime.regexp.joni.constants.OPCode; 25 import jdk.nashorn.internal.runtime.regexp.joni.constants.OPSize; 26 import jdk.nashorn.internal.runtime.regexp.joni.exception.InternalException; 27 28 class ByteCodePrinter { 29 final int[]code; 30 final int codeLength; 31 final char[][] templates; 32 33 Object[]operands; 34 int operantCount; 35 WarnCallback warnings; 36 37 public ByteCodePrinter(Regex regex) { 38 code = regex.code; 39 codeLength = regex.codeLength; 40 operands = regex.operands; 41 operantCount = regex.operandLength; 42 43 templates = regex.templates; 44 warnings = regex.warnings; 45 } 46 47 public String byteCodeListToString() { 48 return compiledByteCodeListToString(); 49 } 50 51 private void pString(StringBuilder sb, int len, int s) { 52 sb.append(":"); 53 while (len-- > 0) sb.append(new String(new byte[]{(byte)code[s++]})); 54 } 55 56 private void pStringFromTemplate(StringBuilder sb, int len, byte[]tm, int idx) { 57 sb.append(":T:"); 58 while (len-- > 0) sb.append(new String(new byte[]{tm[idx++]})); 59 } 60 61 private void pLenString(StringBuilder sb, int len, int mbLen, int s) { 62 int x = len * mbLen; 63 sb.append(":" + len + ":"); 64 while (x-- > 0) sb.append(new String(new byte[]{(byte)code[s++]})); 65 } 66 67 private void pLenStringFromTemplate(StringBuilder sb, int len, int mbLen, char[] tm, int idx) { 68 int x = len * mbLen; 69 sb.append(":T:" + len + ":"); 70 while (x-- > 0) sb.append(new String(new byte[]{(byte)tm[idx++]})); 71 } 72 73 public int compiledByteCodeToString(StringBuilder sb, int bp) { 74 int len, n, mem, addr, scn, cod; 75 BitSet bs; 76 CClassNode cc; 77 int tm, idx; 78 79 sb.append("[" + OPCode.OpCodeNames[code[bp]]); 80 int argType = OPCode.OpCodeArgTypes[code[bp]]; 81 int ip = bp; 82 if (argType != Arguments.SPECIAL) { 83 bp++; 84 switch (argType) { 85 case Arguments.NON: 86 break; 87 88 case Arguments.RELADDR: 89 sb.append(":(" + code[bp] + ")"); 90 bp += OPSize.RELADDR; 91 break; 92 93 case Arguments.ABSADDR: 94 sb.append(":(" + code[bp] + ")"); 95 bp += OPSize.ABSADDR; 96 break; 97 98 case Arguments.LENGTH: 99 sb.append(":" + code[bp]); 100 bp += OPSize.LENGTH; 101 break; 102 103 case Arguments.MEMNUM: 104 sb.append(":" + code[bp]); 105 bp += OPSize.MEMNUM; 106 break; 107 108 case Arguments.OPTION: 109 sb.append(":" + code[bp]); 110 bp += OPSize.OPTION; 111 break; 112 113 case Arguments.STATE_CHECK: 114 sb.append(":" + code[bp]); 115 bp += OPSize.STATE_CHECK; 116 break; 117 } 118 } else { 119 switch (code[bp++]) { 120 case OPCode.EXACT1: 121 case OPCode.ANYCHAR_STAR_PEEK_NEXT: 122 case OPCode.ANYCHAR_ML_STAR_PEEK_NEXT: 123 case OPCode.ANYCHAR_STAR_PEEK_NEXT_SB: 124 case OPCode.ANYCHAR_ML_STAR_PEEK_NEXT_SB: 125 pString(sb, 1, bp++); 126 break; 127 128 case OPCode.EXACT2: 129 pString(sb, 2, bp); 130 bp += 2; 131 break; 132 133 case OPCode.EXACT3: 134 pString(sb, 3, bp); 135 bp += 3; 136 break; 137 138 case OPCode.EXACT4: 139 pString(sb, 4, bp); 140 bp += 4; 141 break; 142 143 case OPCode.EXACT5: 144 pString(sb, 5, bp); 145 bp += 5; 146 break; 147 148 case OPCode.EXACTN: 149 len = code[bp]; 150 bp += OPSize.LENGTH; 151 if (Config.USE_STRING_TEMPLATES) { 152 tm = code[bp]; 153 bp += OPSize.INDEX; 154 idx = code[bp]; 155 bp += OPSize.INDEX; 156 pLenStringFromTemplate(sb, len, 1, templates[tm], idx); 157 } else { 158 pLenString(sb, len, 1, bp); 159 bp += len; 160 } 161 break; 162 163 case OPCode.EXACTMB2N1: 164 pString(sb, 2, bp); 165 bp += 2; 166 break; 167 168 case OPCode.EXACTMB2N2: 169 pString(sb, 4, bp); 170 bp += 4; 171 break; 172 173 case OPCode.EXACTMB2N3: 174 pString(sb, 6, bp); 175 bp += 6; 176 break; 177 178 case OPCode.EXACTMB2N: 179 len = code[bp]; 180 bp += OPSize.LENGTH; 181 if (Config.USE_STRING_TEMPLATES) { 182 tm = code[bp]; 183 bp += OPSize.INDEX; 184 idx = code[bp]; 185 bp += OPSize.INDEX; 186 pLenStringFromTemplate(sb, len, 2, templates[tm], idx); 187 } else { 188 pLenString(sb, len, 2, bp); 189 bp += len * 2; 190 } 191 break; 192 193 case OPCode.EXACTMB3N: 194 len = code[bp]; 195 bp += OPSize.LENGTH; 196 if (Config.USE_STRING_TEMPLATES) { 197 tm = code[bp]; 198 bp += OPSize.INDEX; 199 idx = code[bp]; 200 bp += OPSize.INDEX; 201 pLenStringFromTemplate(sb, len, 3, templates[tm], idx); 202 } else { 203 pLenString(sb, len, 3, bp); 204 bp += len * 3; 205 } 206 break; 207 208 case OPCode.EXACTMBN: 209 int mbLen = code[bp]; 210 bp += OPSize.LENGTH; 211 len = code[bp]; 212 bp += OPSize.LENGTH; 213 n = len * mbLen; 214 215 if (Config.USE_STRING_TEMPLATES) { 216 tm = code[bp]; 217 bp += OPSize.INDEX; 218 idx = code[bp]; 219 bp += OPSize.INDEX; 220 sb.append(":T:" + mbLen + ":" + len + ":"); 221 222 while (n-- > 0) sb.append(new String(new char[]{templates[tm][idx++]})); 223 } else { 224 sb.append(":" + mbLen + ":" + len + ":"); 225 226 while (n-- > 0) sb.append(new String(new byte[]{(byte)code[bp++]})); 227 } 228 229 break; 230 231 case OPCode.EXACT1_IC: 232 case OPCode.EXACT1_IC_SB: 233 final int MAX_CHAR_LENGTH = 6; 234 byte[]bytes = new byte[MAX_CHAR_LENGTH]; 235 for (int i = 0; bp + i < code.length && i < MAX_CHAR_LENGTH; i++) bytes[i] = (byte)code[bp + i]; 236 pString(sb, 1, bp); 237 bp++; 238 break; 239 240 case OPCode.EXACTN_IC: 241 case OPCode.EXACTN_IC_SB: 242 len = code[bp]; 243 bp += OPSize.LENGTH; 244 if (Config.USE_STRING_TEMPLATES) { 245 tm = code[bp]; 246 bp += OPSize.INDEX; 247 idx = code[bp]; 248 bp += OPSize.INDEX; 249 pLenStringFromTemplate(sb, len, 1, templates[tm], idx); 250 } else { 251 pLenString(sb, len, 1, bp); 252 bp += len; 253 } 254 break; 255 256 case OPCode.CCLASS: 257 case OPCode.CCLASS_SB: 258 bs = new BitSet(); 259 System.arraycopy(code, bp, bs.bits, 0, BitSet.BITSET_SIZE); 260 n = bs.numOn(); 261 bp += BitSet.BITSET_SIZE; 262 sb.append(":" + n); 263 break; 264 265 case OPCode.CCLASS_NOT: 266 case OPCode.CCLASS_NOT_SB: 267 bs = new BitSet(); 268 System.arraycopy(code, bp, bs.bits, 0, BitSet.BITSET_SIZE); 269 n = bs.numOn(); 270 bp += BitSet.BITSET_SIZE; 271 sb.append(":" + n); 272 break; 273 274 case OPCode.CCLASS_MB: 275 case OPCode.CCLASS_MB_NOT: 276 len = code[bp]; 277 bp += OPSize.LENGTH; 278 cod = code[bp]; 279 //bp += OPSize.CODE_POINT; 280 bp += len; 281 sb.append(":" + cod + ":" + len); 282 break; 283 284 case OPCode.CCLASS_MIX: 285 case OPCode.CCLASS_MIX_NOT: 286 bs = new BitSet(); 287 System.arraycopy(code, bp, bs.bits, 0, BitSet.BITSET_SIZE); 288 n = bs.numOn(); 289 bp += BitSet.BITSET_SIZE; 290 len = code[bp]; 291 bp += OPSize.LENGTH; 292 cod = code[bp]; 293 //bp += OPSize.CODE_POINT; 294 bp += len; 295 sb.append(":" + n + ":" + cod + ":" + len); 296 break; 297 298 case OPCode.CCLASS_NODE: 299 cc = (CClassNode)operands[code[bp]]; 300 bp += OPSize.POINTER; 301 n = cc.bs.numOn(); 302 sb.append(":" + cc + ":" + n); 303 break; 304 305 case OPCode.BACKREFN_IC: 306 mem = code[bp]; 307 bp += OPSize.MEMNUM; 308 sb.append(":" + mem); 309 break; 310 311 case OPCode.BACKREF_MULTI_IC: 312 case OPCode.BACKREF_MULTI: 313 sb.append(" "); 314 len = code[bp]; 315 bp += OPSize.LENGTH; 316 for (int i=0; i<len; i++) { 317 mem = code[bp]; 318 bp += OPSize.MEMNUM; 319 if (i > 0) sb.append(", "); 320 sb.append(mem); 321 } 322 break; 323 324 case OPCode.BACKREF_WITH_LEVEL: { 325 int option = code[bp]; 326 bp += OPSize.OPTION; 327 sb.append(":" + option); 328 int level = code[bp]; 329 bp += OPSize.LENGTH; 330 sb.append(":" + level); 331 sb.append(" "); 332 len = code[bp]; 333 bp += OPSize.LENGTH; 334 for (int i=0; i<len; i++) { 335 mem = code[bp]; 336 bp += OPSize.MEMNUM; 337 if (i > 0) sb.append(", "); 338 sb.append(mem); 339 } 340 break; 341 } 342 343 case OPCode.REPEAT: 344 case OPCode.REPEAT_NG: 345 mem = code[bp]; 346 bp += OPSize.MEMNUM; 347 addr = code[bp]; 348 bp += OPSize.RELADDR; 349 sb.append(":" + mem + ":" + addr); 350 break; 351 352 case OPCode.PUSH_OR_JUMP_EXACT1: 353 case OPCode.PUSH_IF_PEEK_NEXT: 354 addr = code[bp]; 355 bp += OPSize.RELADDR; 356 sb.append(":(" + addr + ")"); 357 pString(sb, 1, bp); 358 bp++; 359 break; 360 361 case OPCode.LOOK_BEHIND: 362 case OPCode.LOOK_BEHIND_SB: 363 len = code[bp]; 364 bp += OPSize.LENGTH; 365 sb.append(":" + len); 366 break; 367 368 case OPCode.PUSH_LOOK_BEHIND_NOT: 369 addr = code[bp]; 370 bp += OPSize.RELADDR; 371 len = code[bp]; 372 bp += OPSize.LENGTH; 373 sb.append(":" + len + ":(" + addr + ")"); 374 break; 375 376 case OPCode.STATE_CHECK_PUSH: 377 case OPCode.STATE_CHECK_PUSH_OR_JUMP: 378 scn = code[bp]; 379 bp += OPSize.STATE_CHECK_NUM; 380 addr = code[bp]; 381 bp += OPSize.RELADDR; 382 sb.append(":" + scn + ":(" + addr + ")"); 383 break; 384 385 default: 386 throw new InternalException("undefined code: " + code[--bp]); 387 } 388 } 389 390 sb.append("]"); 391 392 // @opcode_address(opcode_size) 393 if (Config.DEBUG_COMPILE_BYTE_CODE_INFO) sb.append("@" + ip + "(" + (bp - ip) + ")"); 394 395 return bp; 396 } 397 398 private String compiledByteCodeListToString() { 399 StringBuilder sb = new StringBuilder(); 400 sb.append("code length: " + codeLength + "\n"); 401 402 int ncode = 0; 403 int bp = 0; 404 int end = codeLength; 405 406 while (bp < end) { 407 ncode++; 408 409 if (bp > 0) sb.append(ncode % 5 == 0 ? "\n" : " "); 410 411 bp = compiledByteCodeToString(sb, bp); 412 } 413 sb.append("\n"); 414 return sb.toString(); 415 } 416 }