1 package gov.nasa.jpf.tools; 20 21 import gov.nasa.jpf.jvm.Types; 22 23 import java.io.PrintWriter ; 24 25 import java.lang.reflect.*; 26 27 28 37 public class GenPeerDispatcher { 38 static final String SYS_PKG = "gov.nasa.jpf.jvm"; 39 static final String INDENT = " "; 40 static final String EXECUTE = "Instruction executeMethod (ThreadInfo ti, MethodInfo mi)"; 41 static final String IS_COND_DETERMINISTIC = "boolean isMethodCondDeterministic (ThreadInfo ti, MethodInfo mi)"; 42 static final String IS_COND_EXECUTABLE = "boolean isMethodCondExecutable (ThreadInfo ti, MethodInfo mi)"; 43 static final String EXEC_COND = "$isExecutable_"; 44 static final String DETERM_COND = "$isDeterministic_"; 45 static final int MJI_MODS = Modifier.PUBLIC | Modifier.STATIC; 46 static String clsName; 47 static PrintWriter pw; 48 static Method[] tmethods; 50 public static void main (String [] args) { 51 if ((args.length == 0) || !readOptions(args)) { 52 showUsage(); 53 54 return; 55 } 56 57 pw = new PrintWriter (System.out, true); 58 59 Class cls = getClass(clsName); 60 61 if (cls != null) { 62 printNativePeerDispatcher(cls); 63 } 64 } 65 66 static Class getClass (String cname) { 67 Class clazz = null; 68 69 try { 70 clazz = Class.forName(cname); 71 } catch (ClassNotFoundException cnfx) { 72 System.err.println("target class not found: " + cname); 73 } catch (Throwable x) { 74 x.printStackTrace(); 75 } 76 77 return clazz; 78 } 79 80 static boolean isMJIDetermCondCandidate (Method m) { 81 if ((m.getModifiers() & MJI_MODS) == MJI_MODS) { 82 String name = m.getName(); 83 84 return name.startsWith(DETERM_COND); 85 } 86 87 return false; 88 } 89 90 static boolean isMJIExecCondCandidate (Method m) { 91 if ((m.getModifiers() & MJI_MODS) == MJI_MODS) { 92 String name = m.getName(); 93 94 return name.startsWith(EXEC_COND); 95 } 96 97 return false; 98 } 99 100 static boolean isMJIExecuteCandidate (Method m) { 101 if ((m.getModifiers() & MJI_MODS) == MJI_MODS) { 102 String name = m.getName(); 103 104 return !(name.startsWith(EXEC_COND) || name.startsWith(DETERM_COND)); 105 } 106 107 return false; 108 } 109 110 static String getSignature (Method m) { 111 String mname = m.getName(); 112 113 if (mname.equals("$clinit") || mname.equals("$init")) { 114 return "()"; 116 } 117 118 Method tm = getTargetMethod(m); 121 122 if (tm != null) { 123 Class [] argTypes = tm.getParameterTypes(); 125 StringBuffer sb = new StringBuffer (); 126 127 sb.append('('); 128 129 for (int i = 0; i < argTypes.length; i++) { 130 Class t = argTypes[i]; 131 132 while (t.isArray()) { 133 sb.append('['); 134 t = t.getComponentType(); 135 } 136 137 if (t == Boolean.TYPE) { 138 sb.append('Z'); 139 } else if (t == Byte.TYPE) { 140 sb.append('B'); 141 } else if (t == Character.TYPE) { 142 sb.append('C'); 143 } else if (t == Short.TYPE) { 144 sb.append('S'); 145 } else if (t == Integer.TYPE) { 146 sb.append('I'); 147 } else if (t == Long.TYPE) { 148 sb.append('J'); 149 } else if (t == Float.TYPE) { 150 sb.append('F'); 151 } else if (t == Double.TYPE) { 152 sb.append('D'); 153 } else { 154 sb.append('L'); 155 sb.append(t.getName().replace('.', '/')); 156 sb.append(';'); 157 } 158 } 159 160 sb.append(')'); 161 162 return sb.toString(); 163 } 164 165 return "()"; } 167 168 static Method getTargetMethod (Method m) { 169 String mname = m.getName(); 171 172 if (tmethods == null) { 173 String tcn = m.getDeclaringClass().getName(); 174 tcn = tcn.substring(tcn.indexOf("JPF") + 4); 175 tcn = tcn.replace('_', '.'); 176 177 try { 178 Class tcls = Class.forName(tcn); 180 tmethods = tcls.getDeclaredMethods(); 181 } catch (ClassNotFoundException cnfx) { 182 System.err.println("!! cannot find target class " + tcn + 183 " to determine signature of: " + mname); 184 185 return null; 186 } 187 } 188 189 for (int i = 0; i < tmethods.length; i++) { 190 if (tmethods[i].getName().equals(mname)) { 191 return tmethods[i]; 192 } 193 } 194 195 System.err.println( 196 "!! cannot find target method to determine signature of: " + mname); 197 198 return null; 199 } 200 201 static int calcStackSize (Class [] argTypes) { 202 int n = 0; 203 204 for (int i = 2; i < argTypes.length; i++) { 207 if ((argTypes[i] == Long.TYPE) || (argTypes[i] == Double.TYPE)) { 208 n += 2; 209 } else { 210 n++; 211 } 212 } 213 214 return n; 215 } 216 217 static void iprint (int level, String s) { 218 printIndent(level); 219 pw.print(s); 220 } 221 222 static void iprintln (int level, String s) { 223 printIndent(level); 224 pw.println(s); 225 } 226 227 static void printCall (Class cls, Method m) { 228 Class [] argTypes = m.getParameterTypes(); 229 Class retType = m.getReturnType(); 230 int stackOffset = calcStackSize(argTypes); 232 pw.print(cls.getName()); 233 pw.print('.'); 234 pw.print(m.getName()); 235 pw.print("( env, rThis"); 236 237 if (argTypes.length > 2) { 238 pw.println(','); 239 } 240 241 for (int i = 2; i < argTypes.length;) { 242 stackOffset--; 243 244 if (argTypes[i] == Boolean.TYPE) { 245 iprint(7, "Types.intToBoolean( ti.peek(" + stackOffset + "))"); 246 } else if (argTypes[i] == Byte.TYPE) { 247 iprint(7, "(byte) ti.peek(" + stackOffset + ")"); 248 } else if (argTypes[i] == Character.TYPE) { 249 iprint(7, "(char) ti.peek(" + stackOffset + ")"); 250 } else if (argTypes[i] == Short.TYPE) { 251 iprint(7, "(short) ti.peek(" + stackOffset + ")"); 252 } else if (argTypes[i] == Integer.TYPE) { 253 iprint(7, "ti.peek(" + stackOffset + ")"); 254 } else if (argTypes[i] == Long.TYPE) { 255 stackOffset--; 256 iprint(7, "ti.longPeek(" + stackOffset + ")"); 257 } else if (argTypes[i] == Float.TYPE) { 258 iprint(7, "Types.intToFloat( ti.peek(" + stackOffset + "))"); 259 } else if (argTypes[i] == Double.TYPE) { 260 stackOffset--; 261 iprint(7, "Types.longToDouble( ti.longPeek(" + stackOffset + "))"); 262 } else { 263 iprint(7, "ti.peek(" + stackOffset + ")"); 264 } 265 266 if ((++i) < argTypes.length) { 267 pw.println(','); 268 } 269 } 270 271 pw.print(")"); 272 } 273 274 static void printCaseConst (Method m) { 275 String mname = m.getName(); 276 String jniname = Types.getJNIMethodName(mname); 277 278 String id = jniname; 279 280 if (id.equals("$clinit")) { 281 id = "<clinit>"; 282 } else if (id.equals("$init")) { 283 id = "<init>"; 284 } 285 286 String argSig = Types.getJNIArgSignature(mname); 287 288 if (argSig != null) { 289 id += argSig; 290 } else { 291 id += getSignature(m); 293 } 294 295 iprint(3, "case "); 296 pw.print(id.hashCode()); 297 pw.print(": // "); 298 pw.println(id); 299 } 300 301 static int printExecCallProlog (Method m) { 302 Class retType = m.getReturnType(); 303 304 if (retType == Void.TYPE) { 305 iprintln(4, "retSize = 0;"); 306 iprint(4, ""); 307 } else if (retType == Boolean.TYPE) { 308 iprintln(4, "retSize = 1;"); 309 iprint(4, "iret = Types.booleanToInt( "); 310 311 return 1; 312 } else if (retType == Byte.TYPE) { 313 iprintln(4, "retSize = 1;"); 314 iprint(4, "iret = (int) "); 315 } else if (retType == Character.TYPE) { 316 iprintln(4, "retSize = 1;"); 317 iprint(4, "iret = (int) "); 318 } else if (retType == Short.TYPE) { 319 iprintln(4, "retSize = 1;"); 320 iprint(4, "iret = (int) "); 321 } else if (retType == Integer.TYPE) { 322 iprintln(4, "retSize = 1;"); 323 iprint(4, "iret = "); 324 } else if (retType == Long.TYPE) { 325 iprintln(4, "retSize = 2;"); 326 iprint(4, "lret = "); 327 } else if (retType == Float.TYPE) { 328 iprintln(4, "retSize = 1;"); 329 iprint(4, "iret = Types.floatToInt( "); 330 331 return 1; 332 } else if (retType == Double.TYPE) { 333 iprintln(4, "retSize = 2;"); 334 iprint(4, "lret = Types.doubleToLong( "); 335 336 return 1; 337 } else { 338 iprintln(4, "retSize = 1;"); 339 iprint(4, "iret = "); 340 } 341 342 return 0; 343 } 344 345 static void printExecute (Class cls) { 346 Method[] mths = cls.getDeclaredMethods(); 347 348 iprint(1, EXECUTE); 349 pw.println(" {"); 350 351 iprintln(2, "int iret = 0;"); 352 iprintln(2, "long lret = 0;"); 353 iprintln(2, "int retSize = 0;"); 354 iprintln(2, "String exception = null;"); 355 iprintln(2, "int mid = mi.getUniqueName().hashCode();"); 356 pw.println(); 357 358 iprintln(2, "MJIEnv env = ti.getMJIEnv();"); 359 iprintln(2, 360 "int rThis = (mi.isStatic()) ? ci.getClassObjectRef() : ti.getCalleeThis(mi);"); 361 pw.println(); 362 363 iprintln(2, "env.setCallEnvironment( mi);"); 364 pw.println(); 365 366 iprintln(2, "try {"); 367 368 iprintln(3, "switch (mid) {"); 369 370 for (int i = 0; i < mths.length; i++) { 371 Method m = mths[i]; 372 373 if (isMJIExecuteCandidate(m)) { 374 printCaseConst(m); 375 376 int openFuncs = printExecCallProlog(m); 377 printCall(cls, m); 378 379 for (int j = 0; j < openFuncs; j++) { 380 pw.print(')'); 381 } 382 383 pw.println(';'); 384 iprintln(4, "break;"); 385 } 386 } 387 388 iprintln(3, "default:"); 389 iprintln(4, 390 "return ti.createAndThrowException( \"java.lang.UnsatisfiedLinkError\","); 391 iprintln(6, "\"cannot find: \" + ci.getName() + '.' + mi.getName());"); 392 393 iprintln(3, "}"); 394 395 iprintln(2, "} catch (Throwable x) {"); 396 iprintln(3, "x.printStackTrace();"); 397 iprintln(3, 398 "return ti.createAndThrowException( \"java.lang.reflect.InvocationTargetException\","); 399 iprintln(5, "ci.getName() + '.' + mi.getName());"); 400 iprintln(2, "}"); 401 402 pw.println(); 403 iprintln(2, "if ((exception = env.getException()) != null) {"); 404 iprintln(3, "return ti.createAndThrowException(exception);"); 405 iprintln(2, "}"); 406 pw.println(); 407 iprintln(2, "if (env.getRepeat()) {"); 408 iprintln(3, "return ti.getPC();"); 409 iprintln(2, "}"); 410 pw.println(); 411 iprintln(2, "ti.removeArguments(mi);"); 412 pw.println(); 413 iprintln(2, "switch (retSize) {"); 414 iprintln(2, "case 0: break; // nothing to return"); 415 iprintln(2, "case 1: ti.push(iret, mi.isReferenceReturnType()); break;"); 416 iprintln(2, "case 2: ti.longPush(lret); break;"); 417 iprintln(2, "}"); 418 pw.println(); 419 iprintln(2, "return ti.getPC().getNext();"); 420 421 iprintln(1, "}"); 422 } 423 424 static void printFooter (Class cls) { 425 pw.println("}"); 426 } 427 428 static void printHeader (Class cls) { 429 pw.print("package "); 430 pw.print(SYS_PKG); 431 pw.println(';'); 432 pw.println(); 433 434 String cname = cls.getName(); 435 int idx = cname.lastIndexOf('.'); 436 437 if (idx > 0) { 438 cname = cname.substring(idx + 1); 439 } 440 441 pw.println("import gov.nasa.jpf.JPFVMException;"); 442 pw.println("import gov.nasa.jpf.jvm.bytecode.Instruction;"); 443 pw.println(); 444 445 pw.print("class "); 446 pw.print(cname); 447 pw.println("$ extends NativePeer {"); 448 } 449 450 static void printIndent (int level) { 451 for (int i = 0; i < level; i++) { 452 pw.print(INDENT); 453 } 454 } 455 456 static void printIsCond (Class cls, String condPrefix) { 457 Method[] mths = cls.getDeclaredMethods(); 458 459 iprint(1, condPrefix); 460 pw.println(" {"); 461 462 iprintln(2, "boolean ret = false;"); 463 iprintln(2, "int mid = mi.getUniqueName().hashCode();"); 464 pw.println(); 465 466 iprintln(2, "MJIEnv env = ti.getMJIEnv();"); 467 iprintln(2, 468 "int rThis = (mi.isStatic()) ? ci.getClassObjectRef() : ti.getCalleeThis(mi);"); 469 pw.println(); 470 471 iprintln(2, "env.setCallEnvironment( mi);"); 472 pw.println(); 473 474 iprintln(2, "try {"); 475 476 iprintln(3, "switch (mid) {"); 477 478 for (int i = 0; i < mths.length; i++) { 479 Method m = mths[i]; 480 481 if (((condPrefix == IS_COND_DETERMINISTIC) && 482 isMJIDetermCondCandidate(m)) || 483 ((condPrefix == IS_COND_EXECUTABLE) && 484 isMJIExecCondCandidate(m))) { 485 printCaseConst(m); 486 487 iprint(4, "ret = "); 488 printCall(cls, m); 489 pw.println(';'); 490 } 491 } 492 493 iprintln(3, "default:"); 494 495 if (condPrefix == IS_COND_EXECUTABLE) { 496 iprintln(4, 497 "throw new JPFVMException(\"no isExecutable() condition: \" + mi.getName());"); 498 } else { 499 iprintln(4, 500 "throw new JPFVMException(\"no isDeterministic() condition: \" + mi.getName());"); 501 } 502 503 iprintln(3, "}"); 504 505 iprintln(2, "} catch (Throwable x) {"); 506 iprintln(3, "x.printStackTrace();"); 507 iprintln(2, "}"); 508 pw.println(); 509 510 iprintln(2, "return ret;"); 511 iprintln(1, "}"); 512 } 513 514 static void printIsCondDeterministic (Class cls) { 515 printIsCond(cls, IS_COND_DETERMINISTIC); 516 } 517 518 static void printIsCondExecutable (Class cls) { 519 printIsCond(cls, IS_COND_EXECUTABLE); 520 } 521 522 static void printNativePeerDispatcher (Class cls) { 523 printHeader(cls); 524 pw.println(); 525 526 printExecute(cls); 527 pw.println(); 528 printIsCondDeterministic(cls); 529 pw.println(); 530 printIsCondExecutable(cls); 531 pw.println(); 532 533 printFooter(cls); 534 } 535 536 static boolean readOptions (String [] args) { 537 for (int i = 0; i < args.length; i++) { 538 String arg = args[i]; 539 540 if (arg.charAt(0) == '-') { 541 System.err.println("unknown option: " + arg); 542 showUsage(); 543 544 return false; 545 } else { 546 if (clsName == null) { 547 clsName = arg; 548 } 549 } 550 } 551 552 return (clsName != null); 553 } 554 555 static void showUsage () { 556 System.out.println("usage: 'GenPeerDispatcher <className>'"); 557 } 558 } | Popular Tags |