Indify.java revision 4250
0N/A * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved. 0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 0N/A * This code is free software; you can redistribute it and/or modify it 0N/A * under the terms of the GNU General Public License version 2 only, as 0N/A * published by the Free Software Foundation. Oracle designates this 0N/A * particular file as subject to the "Classpath" exception as provided 0N/A * by Oracle in the LICENSE file that accompanied this code. 0N/A * This code is distributed in the hope that it will be useful, but WITHOUT 0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 0N/A * version 2 for more details (a copy is included in the LICENSE file that 0N/A * accompanied this code). 0N/A * You should have received a copy of the GNU General Public License version 0N/A * 2 along with this work; if not, write to the Free Software Foundation, 0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 0N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 0N/A * or visit www.oracle.com if you need additional information or have any 0N/A * Transform one or more class files to incorporate JSR 292 features, 0N/A * such as {@code invokedynamic}. 0N/A * This is a standalone program in a single source file. 0N/A * In this form, it may be useful for test harnesses, small experiments, and javadoc examples. 0N/A * Copies of this file may show up in multiple locations for standalone usage. 0N/A * The primary maintained location of this file is as follows: 0N/A * Static private methods named MH_x and MT_x (where x is arbitrary) 0N/A * must be stereotyped generators of MethodHandle and MethodType 0N/A * constants. All calls to them are transformed to {@code CONSTANT_MethodHandle} 0N/A * and {@code CONSTANT_MethodType} "ldc" instructions. 0N/A * The stereotyped code must create method types by calls to {@code methodType} or 0N/A * {@code fromMethodDescriptorString}. The "lookup" argument must be created 0N/A * by calls to {@code java.lang.invoke.MethodHandles#lookup MethodHandles.lookup}. 0N/A * The class and string arguments must be constant. 0N/A * The following methods of {@code java.lang.invoke.MethodHandle.Lookup Lookup} are 0N/A * allowed for method handle creation: {@code findStatic}, {@code findVirtual}, 0N/A * {@code findConstructor}, {@code findSpecial}, 0N/A * {@code findGetter}, {@code findSetter}, 0N/A * {@code findStaticGetter}, or {@code findStaticSetter}. 0N/A * The call to one of these methods must be followed immediately 0N/A * by an {@code areturn} instruction. 0N/A * The net result of the call to the MH_x or MT_x method must be 0N/A * the creation of a constant method handle. Thus, replacing calls 0N/A * to MH_x or MT_x methods by {@code ldc} instructions should leave 0N/A * the meaning of the program unchanged. 0N/A * Static private methods named INDY_x must be stereotyped generators 0N/A * of {@code invokedynamic} call sites. 0N/A * All calls to them must be immediately followed by 0N/A * {@code invokeExact} calls. 0N/A * All such pairs of calls are transformed to {@code invokedynamic} 0N/A * instructions. Each INDY_x method must begin with a call to a 0N/A * MH_x method, which is taken to be its bootstrap method. 0N/A * The method must be immediately invoked (via {@code invokeGeneric} 0N/A * on constant lookup, name, and type arguments. An object array of 0N/A * constants may also be appended to the {@code invokeGeneric call}. 0N/A * This call must be cast to {@code CallSite}, and the result must be 0N/A * immediately followed by a call to {@code dynamicInvoker}, with the 0N/A * resulting method handle returned. 0N/A * The net result of all of these actions is equivalent to the JVM's 0N/A * execution of an {@code invokedynamic} instruction in the unlinked state. 0N/A * Running this code once should produce the same results as running 0N/A * the corresponding {@code invokedynamic} instruction. 0N/A * In order to model the caching behavior, the code of an INDY_x 0N/A * method is allowed to begin with getstatic, aaload, and if_acmpne 0N/A * instructions which load a static method handle value and return it 0N/A * if the value is non-null. 0N/A$ JAVA_HOME=(some recent OpenJDK 7 build) 0N/AMT = (java.lang.Object)java.lang.Object 0N/AMH = adder(int,int)java.lang.Integer 0N/A(same output as above) 0N/A * </pre></blockquote> 0N/A /** Execute the given application under a class loader which indifies all application classes. */ 0N/A return;
// keep this argument 0N/A case "-d":
case "--dest":
case "-d=":
case "--dest=":
0N/A case "-cp":
case "--classpath":
0N/A case "-k":
case "--keepgoing":
case "--keepgoing=":
0N/A case "--expand-properties":
case "--expand-properties=":
0N/A case "--verify-specifier-count":
case "--verify-specifier-count=":
0N/A case "--overwrite":
case "--overwrite=":
0N/A case "--all":
case "--all=":
0N/A case "-q":
case "--quiet":
case "--quiet=":
0N/A case "-v":
case "--verbose":
case "--verbose=":
0N/A case "true":
case "yes":
case "on":
case "1":
return true;
0N/A case "false":
case "no":
case "off":
case "0":
return false;
0N/A outfile = f;
// overwrite input file, no matter where it is 0N/A // return true if it might be a package name: 0N/A // pass error from reportPatternMethods, etc. 0N/A //System.out.println("Checking for "+f); 0N/A // Indify logic, per se. 0N/A //for (Constant c : cp) System.out.println(" # "+c); 0N/A // Transform references. 0N/A //if (blab == 1) { for (Instruction j = m.instructions(); j != null; j = j.next()) System.out.println(" |"+j); } 0N/A // need to patch the following instruction too, 0N/A // but there are usually intervening argument pushes too 0N/A //System.out.println(new Instruction(i.codeBase, i2.pc-3)); 0N/A //if (blab >= 1) { for (Instruction j = m.instructions(); j != null; j = j.next()) System.out.println(" |"+j); } 0N/A // Scan forward from the instruction to find where the stack p 0N/A // below the current sp at the instruction. 0N/A //System.out.println("findPop from "+i); 0N/A //System.out.println(" "+i+" "+jvm.stack+" : "+pops.replace("$", " => ")); 0N/A //System.out.println("special type: "+type+" => "+pops); 0N/A // Pass by specsLen == 0, to help with associated (inner) classes. 0N/A // mark constant pool entries according to participation in patterns 0N/A mark =
cmark;
// it is a java.lang.invoke.* or java.lang.* method 0N/A case 'T':
case 'H':
case 'I':
0N/A // ? also: dup2{,_x1,_x2} 0N/A default:
return false;
0N/A //System.out.println(jvm.stack+" "+i); 0N/A // these support creation of a restarg array 0N/A //System.out.println("new "+type); 0N/A // int.class compiles to getstatic Integer.TYPE 0N/A //System.err.println("getstatic "+fieldi+Arrays.asList(pool.getStrings(pool.getMemberRef((short)fieldi)))+mark); 0N/A // a primitive type descriptor 0N/A // unknown field; keep going... 0N/A // unknown field; keep going... 0N/A //System.out.println("invoke "+pool.getString(CONSTANT_Utf8, ref[1])+" "+Arrays.asList(ref)+" : "+type); 0N/A //System.out.println("recognized intrinsic "+intrinsic); 0N/A //if (intrinsic != null) System.out.println("intrinsic = "+intrinsic); 0N/A case "fromMethodDescriptorString":
0N/A case "methodType": {
0N/A // should not happen, but... 0N/A // first arg is treated differently 0N/A case "dynamicInvoker":
0N/A // fold lookup().lookupClass() to the enclosing class 0N/A case "invokeGeneric":
0N/A case "invokeWithArguments":
0N/A case "Integer.valueOf":
0N/A case "Float.valueOf":
0N/A case "Long.valueOf":
0N/A case "Double.valueOf":
0N/A case "StringBuilder.append":
0N/A // allow calls like ("value = "+x) 0N/A case "StringBuilder.toString":
0N/A // allow calls like println("reached the pattern method") 0N/A // parse bsmArgs as (MH, lookup, String, MT, [extra]) 0N/A break;
// merge to next path 0N/A // these support caching paths in INDY_x methods 0N/A // ignore branch target 0N/A break;
// assume it is a helpful cast 0N/A // E.g.: lookup().findStatic(Foo.class, "name", MethodType) 0N/A // E.g.: MH_bsm.invokeGeneric(lookup(), "name", MethodType, "extraArg") bsms =
new Attr(
cf,
"BootstrapMethods",
new byte[]{
0,
0});
for (
int i =
0; i <
len; i++) {
for (
int j =
0; j <
argc; j++)
private interface Chunk {
for (
int i =
0; i <
rowlen; i++)
}
else if (
data instanceof byte[]) {
public static abstract class Outer {
//if (!(walk instanceof Inner)) return null; TAG_NAMES = (
"None Utf8 Unicode Integer Float Long Double Class String" +
" Fieldref Methodref InterfaceMethodref NameAndType #13 #14" +
" MethodHandle MethodType InvokeDynamic#17 InvokeDynamic").
split(
" ");
add(
null);
// always ignore first item // read an ordered pair; first part is a u1 (not u2) // extra 1-bits get into the shorts if (x !=
null)
return (
char)(
int) x;
public int size = -
1;
// no pre-declared size // write the 4-byte size header and then the contents: if (
item instanceof byte[]) {
//if (!(item instanceof Code)) System.err.println("wrote complex attr name="+(int)(char)name+" size="+trueSize+" data="+Arrays.toString(flatten())); if (
item instanceof byte[] &&
// etable[N] = (N)*{ startpc, endpc, handlerpc, catchtype } private static final byte private static final byte -
1,
0,
1,
2,
3,
4,
5,
0L,
1L,
0.0F,
1.0F,
2.0F,
0.0D,
1.0D "nop$ aconst_null$L iconst_m1$I iconst_0$I iconst_1$I "+
"iconst_2$I iconst_3$I iconst_4$I iconst_5$I lconst_0$J_ "+
"lconst_1$J_ fconst_0$F fconst_1$F fconst_2$F dconst_0$D_ "+
"dconst_1$D_ bipush=bx$I sipush=bxx$I ldc=bk$X ldc_w=bkk$X "+
"iload_2$I iload_3$I lload_0$J_ lload_1$J_ lload_2$J_ "+
"lload_3$J_ fload_0$F fload_1$F fload_2$F fload_3$F dload_0$D_ "+
"dload_1$D_ dload_2$D_ dload_3$D_ aload_0$L aload_1$L "+
"aload_2$L aload_3$L iaload$LI$I laload$LI$J_ faload$LI$F "+
"daload$LI$D_ aaload$LI$L baload$LI$I caload$LI$I saload$LI$I "+
"dstore=bl/wbll$D_$ astore=bl/wbll$L$ istore_0$I$ istore_1$I$ "+
"istore_2$I$ istore_3$I$ lstore_0$J_$ lstore_1$J_$ "+
"lstore_2$J_$ lstore_3$J_$ fstore_0$F$ fstore_1$F$ fstore_2$F$ "+
"fstore_3$F$ dstore_0$D_$ dstore_1$D_$ dstore_2$D_$ "+
"dstore_3$D_$ astore_0$L$ astore_1$L$ astore_2$L$ astore_3$L$ "+
"iastore$LII$ lastore$LIJ_$ fastore$LIF$ dastore$LID_$ "+
"aastore$LIL$ bastore$LII$ castore$LII$ sastore$LII$ pop$X$ "+
"pop2$XX$ dup$X$XX dup_x1$XX$XXX dup_x2$XXX$XXXX dup2$XX$XXXX "+
"dup2_x1$XXX$XXXXX dup2_x2$XXXX$XXXXXX swap$XX$XX "+
"iadd$II$I ladd$J_J_$J_ fadd$FF$F dadd$D_D_$D_ isub$II$I "+
"lsub$J_J_$J_ fsub$FF$F dsub$D_D_$D_ imul$II$I lmul$J_J_$J_ "+
"fmul$FF$F dmul$D_D_$D_ idiv$II$I ldiv$J_J_$J_ fdiv$FF$F "+
"ddiv$D_D_$D_ irem$II$I lrem$J_J_$J_ frem$FF$F drem$D_D_$D_ "+
"ineg$I$I lneg$J_$J_ fneg$F$F dneg$D_$D_ ishl$II$I lshl$J_I$J_ "+
"ishr$II$I lshr$J_I$J_ iushr$II$I lushr$J_I$J_ iand$II$I "+
"land$J_J_$J_ ior$II$I lor$J_J_$J_ ixor$II$I lxor$J_J_$J_ "+
"iinc=blx/wbllxx$ i2l$I$J_ i2f$I$F i2d$I$D_ l2i$J_$I l2f$J_$F "+
"l2d$J_$D_ f2i$F$I f2l$F$J_ f2d$F$D_ d2i$D_$I d2l$D_$J_ "+
"d2f$D_$F i2b$I$I i2c$I$I i2s$I$I lcmp fcmpl fcmpg dcmpl dcmpg "+
"ifeq=boo ifne=boo iflt=boo ifge=boo ifgt=boo ifle=boo "+
"if_icmpeq=boo if_icmpne=boo if_icmplt=boo if_icmpge=boo "+
"if_icmpgt=boo if_icmple=boo if_acmpeq=boo if_acmpne=boo "+
"goto=boo jsr=boo ret=bl/wbll tableswitch=* lookupswitch=* "+
"ireturn lreturn freturn dreturn areturn return "+
"getstatic=bkf$Q putstatic=bkf$Q$ getfield=bkf$L$Q "+
"putfield=bkf$LQ$ invokevirtual=bkm$LQ$Q "+
"invokespecial=bkm$LQ$Q invokestatic=bkm$Q$Q "+
"invokeinterface=bkixx$LQ$Q invokedynamic=bkd__$Q$Q new=bkc$L "+
"newarray=bx$I$L anewarray=bkc$I$L arraylength$L$I athrow "+
"checkcast=bkc$L$L instanceof=bkc$L$I monitorenter$L "+
"monitorexit$L wide=* multianewarray=bkcx ifnull=boo "+
"ifnonnull=boo goto_w=boooo jsr_w=boooo ";
int[]
info =
new int[
256];
if (p.
indexOf(
'$') <
0) p =
"$" + p;
// these are the hard parts // clget the Nth int (where 0 is the first after the opcode itself) pos += ((-
pos) &
0x03);
// align it // change (DD)D to (D_D_)D_