public String className(int idx) { Constant c; c = constants[idx]; if (c.tag() == Constant.UTF8) { String s = (String) c.value(); return s.replace('/', '.'); } return null; }
/** Get the class name at the given constant pool index. */ public String classNameCP(int index) { Constant c = constants[index]; if (c != null && c.tag() == Constant.CLASS) { Integer nameIndex = (Integer) c.value(); if (nameIndex != null) { return className(nameIndex.intValue()); } } return null; }
/** * Get the name of the class, including the package name. * * @return The name of the class. */ public String name() { Constant c = constants[thisClass]; if (c.tag() == Constant.CLASS) { Integer nameIndex = (Integer) c.value(); if (nameIndex != null) { c = constants[nameIndex.intValue()]; if (c.tag() == Constant.UTF8) { return (String) c.value(); } } } throw new ClassFormatError("Couldn't find class name in file"); }
/** Get the class name at the given constant pool index. */ public String classNameCP(int index) { Constant c = constants[index]; if (c != null && c.tag() == Constant.CLASS) { Integer nameIndex = (Integer) c.value(); if (nameIndex != null) { c = constants[nameIndex.intValue()]; if (c.tag() == Constant.UTF8) { String s = (String) c.value(); return s.replace('/', '.'); } } } return null; }
static void optimize(final File f, final File d, final Remapper remapper) throws IOException { if (f.isDirectory()) { File[] files = f.listFiles(); for (int i = 0; i < files.length; ++i) { optimize(files[i], d, remapper); } } else if (f.getName().endsWith(".class")) { ConstantPool cp = new ConstantPool(); ClassReader cr = new ClassReader(new FileInputStream(f)); // auto-boxing removal requires to recompute the maxs ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); ClassConstantsCollector ccc = new ClassConstantsCollector(cw, cp); ClassOptimizer co = new ClassOptimizer(ccc, remapper); cr.accept(co, ClassReader.SKIP_DEBUG); Set<Constant> constants = new TreeSet<Constant>(new ConstantComparator()); constants.addAll(cp.values()); cr = new ClassReader(cw.toByteArray()); cw = new ClassWriter(0); Iterator<Constant> i = constants.iterator(); while (i.hasNext()) { Constant c = i.next(); c.write(cw); } cr.accept(cw, ClassReader.SKIP_DEBUG); if (MAPPING.get(cr.getClassName() + "/remove") != null) { return; } String n = remapper.mapType(cr.getClassName()); File g = new File(d, n + ".class"); if (!g.exists() || g.lastModified() < f.lastModified()) { if (!g.getParentFile().exists() && !g.getParentFile().mkdirs()) { throw new IOException("Cannot create directory " + g.getParentFile()); } OutputStream os = new FileOutputStream(g); try { os.write(cw.toByteArray()); } finally { os.close(); } } } }
private Constant sub_compute(Constant c1, Constant c2) { return Constant.create(c1.intValue() - c2.intValue()); }
private Constant add_compute(Constant c1, Constant c2) { return Constant.create(c1.intValue() + c2.intValue()); }
private Constant div_compute(Constant c1, Constant c2) { return Constant.create(c1.intValue() / c2.intValue()); }
private Constant mul_compute(Constant c1, Constant c2) { return Constant.create(c1.intValue() * c2.intValue()); }
private Constant bitNot_compute(Constant c) { return Constant.create(~c.intValue()); }
private Constant constant_compute() { return Constant.create(getLITERAL()); }
private Constant questionColon_compute(Constant cond, Constant c1, Constant c2) { return Constant.create(cond.booleanValue() ? c1.intValue() : c2.intValue()); }
private Constant constant_compute() { return Constant.create(!binaryNumericPromotedType().eqIsTrue(left(), right())); }
/** @apilevel internal */ private Constant mod_compute(Constant c1, Constant c2) { return Constant.create(c1.floatValue() % c2.floatValue()); }
/** * Adds all the constants found in the given class into the given ConstantSet, and returns it. * * @see #getConstants(String) */ public static ConstantSet getConstants(String classname, ConstantSet result) { ClassParser cp; JavaClass jc; try { String classfileBase = classname.replace('.', '/'); InputStream is = ClassPath.SYSTEM_CLASS_PATH.getInputStream(classfileBase, ".class"); cp = new ClassParser(is, classname); jc = cp.parse(); } catch (java.io.IOException e) { throw new Error("IOException while reading '" + classname + "': " + e.getMessage()); } result.classname = jc.getClassName(); // Get all of the constants from the pool ConstantPool constant_pool = jc.getConstantPool(); for (Constant c : constant_pool.getConstantPool()) { // System.out.printf ("*Constant = %s%n", c); if (c == null || c instanceof ConstantClass || c instanceof ConstantFieldref || c instanceof ConstantInterfaceMethodref || c instanceof ConstantMethodref || c instanceof ConstantNameAndType || c instanceof ConstantUtf8) { continue; } if (c instanceof ConstantString) { result.strings.add((String) ((ConstantString) c).getConstantValue(constant_pool)); } else if (c instanceof ConstantDouble) { result.doubles.add((Double) ((ConstantDouble) c).getConstantValue(constant_pool)); } else if (c instanceof ConstantFloat) { result.floats.add((Float) ((ConstantFloat) c).getConstantValue(constant_pool)); } else if (c instanceof ConstantInteger) { result.ints.add((Integer) ((ConstantInteger) c).getConstantValue(constant_pool)); } else if (c instanceof ConstantLong) { result.longs.add((Long) ((ConstantLong) c).getConstantValue(constant_pool)); } else { throw new RuntimeException("Unrecognized constant of type " + c.getClass() + ": " + c); } } ClassGen gen = new ClassGen(jc); ConstantPoolGen pool = gen.getConstantPool(); // Process the code in each method looking for literals for (Method m : jc.getMethods()) { MethodGen mg = new MethodGen(m, jc.getClassName(), pool); InstructionList il = mg.getInstructionList(); if (il == null) { // System.out.println("No instructions for " + mg); } else { for (Instruction inst : il.getInstructions()) { switch (inst.getOpcode()) { // Compare two objects, no literals case Constants.IF_ACMPEQ: case Constants.IF_ACMPNE: break; // These instructions compare the integer on the top of the stack // to zero. There are no literals here (except 0) case Constants.IFEQ: case Constants.IFNE: case Constants.IFLT: case Constants.IFGE: case Constants.IFGT: case Constants.IFLE: { break; } // Instanceof pushes either 0 or 1 on the stack depending on whether // the object on top of stack is of the specified type. // If were interested in class literals, this would be interesting case Constants.INSTANCEOF: break; // Duplicates the item on the top of stack. No literal. case Constants.DUP: { break; } // Duplicates the item on the top of the stack and inserts it 2 // values down in the stack. No literals case Constants.DUP_X1: { break; } // Duplicates either the top 2 category 1 values or a single // category 2 value and inserts it 2 or 3 values down on the // stack. case Constants.DUP2_X1: { break; } // Duplicate either one category 2 value or two category 1 values. case Constants.DUP2: { break; } // Dup the category 1 value on the top of the stack and insert it either // two or three values down on the stack. case Constants.DUP_X2: { break; } case Constants.DUP2_X2: { break; } // Pop instructions discard the top of the stack. case Constants.POP: { break; } // Pops either the top 2 category 1 values or a single category 2 value // from the top of the stack. case Constants.POP2: { break; } // Swaps the two category 1 types on the top of the stack. case Constants.SWAP: { break; } // Compares two integers on the stack case Constants.IF_ICMPEQ: case Constants.IF_ICMPGE: case Constants.IF_ICMPGT: case Constants.IF_ICMPLE: case Constants.IF_ICMPLT: case Constants.IF_ICMPNE: { break; } // Get the value of a field case Constants.GETFIELD: { break; } // stores the top of stack into a field case Constants.PUTFIELD: { break; } // Pushes the value of a static field on the stack case Constants.GETSTATIC: { break; } // Pops a value off of the stack into a static field case Constants.PUTSTATIC: { break; } // pushes a local onto the stack case Constants.DLOAD: case Constants.DLOAD_0: case Constants.DLOAD_1: case Constants.DLOAD_2: case Constants.DLOAD_3: case Constants.FLOAD: case Constants.FLOAD_0: case Constants.FLOAD_1: case Constants.FLOAD_2: case Constants.FLOAD_3: case Constants.ILOAD: case Constants.ILOAD_0: case Constants.ILOAD_1: case Constants.ILOAD_2: case Constants.ILOAD_3: case Constants.LLOAD: case Constants.LLOAD_0: case Constants.LLOAD_1: case Constants.LLOAD_2: case Constants.LLOAD_3: { break; } // Pops a value off of the stack into a local case Constants.DSTORE: case Constants.DSTORE_0: case Constants.DSTORE_1: case Constants.DSTORE_2: case Constants.DSTORE_3: case Constants.FSTORE: case Constants.FSTORE_0: case Constants.FSTORE_1: case Constants.FSTORE_2: case Constants.FSTORE_3: case Constants.ISTORE: case Constants.ISTORE_0: case Constants.ISTORE_1: case Constants.ISTORE_2: case Constants.ISTORE_3: case Constants.LSTORE: case Constants.LSTORE_0: case Constants.LSTORE_1: case Constants.LSTORE_2: case Constants.LSTORE_3: { break; } // Push a value from the runtime constant pool. We'll get these // values when processing the constant pool itself case Constants.LDC: case Constants.LDC_W: case Constants.LDC2_W: { break; } // Push the length of an array on the stack case Constants.ARRAYLENGTH: { break; } // Push small constants (-1..5) on the stack. These literals are // too common to bother mentioning case Constants.DCONST_0: case Constants.DCONST_1: case Constants.FCONST_0: case Constants.FCONST_1: case Constants.FCONST_2: case Constants.ICONST_0: case Constants.ICONST_1: case Constants.ICONST_2: case Constants.ICONST_3: case Constants.ICONST_4: case Constants.ICONST_5: case Constants.ICONST_M1: case Constants.LCONST_0: case Constants.LCONST_1: { break; } case Constants.BIPUSH: case Constants.SIPUSH: { ConstantPushInstruction cpi = (ConstantPushInstruction) inst; result.ints.add((Integer) cpi.getValue()); break; } // Primitive Binary operators. case Constants.DADD: case Constants.DCMPG: case Constants.DCMPL: case Constants.DDIV: case Constants.DMUL: case Constants.DREM: case Constants.DSUB: case Constants.FADD: case Constants.FCMPG: case Constants.FCMPL: case Constants.FDIV: case Constants.FMUL: case Constants.FREM: case Constants.FSUB: case Constants.IADD: case Constants.IAND: case Constants.IDIV: case Constants.IMUL: case Constants.IOR: case Constants.IREM: case Constants.ISHL: case Constants.ISHR: case Constants.ISUB: case Constants.IUSHR: case Constants.IXOR: case Constants.LADD: case Constants.LAND: case Constants.LCMP: case Constants.LDIV: case Constants.LMUL: case Constants.LOR: case Constants.LREM: case Constants.LSHL: case Constants.LSHR: case Constants.LSUB: case Constants.LUSHR: case Constants.LXOR: break; case Constants.LOOKUPSWITCH: case Constants.TABLESWITCH: break; case Constants.ANEWARRAY: case Constants.NEWARRAY: { break; } case Constants.MULTIANEWARRAY: { break; } // push the value at an index in an array case Constants.AALOAD: case Constants.BALOAD: case Constants.CALOAD: case Constants.DALOAD: case Constants.FALOAD: case Constants.IALOAD: case Constants.LALOAD: case Constants.SALOAD: { break; } // Pop the top of stack into an array location case Constants.AASTORE: case Constants.BASTORE: case Constants.CASTORE: case Constants.DASTORE: case Constants.FASTORE: case Constants.IASTORE: case Constants.LASTORE: case Constants.SASTORE: break; case Constants.ARETURN: case Constants.DRETURN: case Constants.FRETURN: case Constants.IRETURN: case Constants.LRETURN: case Constants.RETURN: { break; } // subroutine calls. case Constants.INVOKESTATIC: case Constants.INVOKEVIRTUAL: case Constants.INVOKESPECIAL: case Constants.INVOKEINTERFACE: break; // Throws an exception. case Constants.ATHROW: break; // Opcodes that don't need any modifications. Here for reference case Constants.ACONST_NULL: case Constants.ALOAD: case Constants.ALOAD_0: case Constants.ALOAD_1: case Constants.ALOAD_2: case Constants.ALOAD_3: case Constants.ASTORE: case Constants.ASTORE_0: case Constants.ASTORE_1: case Constants.ASTORE_2: case Constants.ASTORE_3: case Constants.CHECKCAST: case Constants.D2F: // double to float case Constants.D2I: // double to integer case Constants.D2L: // double to long case Constants.DNEG: // Negate double on top of stack case Constants.F2D: // float to double case Constants.F2I: // float to integer case Constants.F2L: // float to long case Constants.FNEG: // Negate float on top of stack case Constants.GOTO: case Constants.GOTO_W: case Constants.I2B: // integer to byte case Constants.I2C: // integer to char case Constants.I2D: // integer to double case Constants.I2F: // integer to float case Constants.I2L: // integer to long case Constants.I2S: // integer to short case Constants.IFNONNULL: case Constants.IFNULL: case Constants.IINC: // increment local variable by a constant case Constants.INEG: // negate integer on top of stack case Constants.JSR: // pushes return address on the stack, case Constants.JSR_W: case Constants.L2D: // long to double case Constants.L2F: // long to float case Constants.L2I: // long to int case Constants.LNEG: // negate long on top of stack case Constants.MONITORENTER: case Constants.MONITOREXIT: case Constants.NEW: case Constants.NOP: case Constants.RET: // this is the internal JSR return break; // Make sure we didn't miss anything default: throw new Error("instruction " + inst + " unsupported"); } } } } return result; }
private Constant urshift_compute(Constant c1, Constant c2) { return Constant.create(c1.intValue() >>> c2.intValue()); }
private Constant orBitwise_compute(Constant c1, Constant c2) { return Constant.create(c1.intValue() | c2.intValue()); }
private Constant cast_compute(Constant c) { return Constant.create(c.intValue()); }
private void readConstantPool(int size) throws IOException { final Constant[] myConstantPool = new Constant[size]; for (int i = 0; i != size; ++i) { int code = input.read_uv(); Constant constant; switch (code) { case WyilFileWriter.CONSTANT_Null: constant = Constant.V_NULL; break; case WyilFileWriter.CONSTANT_False: constant = Constant.V_BOOL(false); break; case WyilFileWriter.CONSTANT_True: constant = Constant.V_BOOL(true); break; case WyilFileWriter.CONSTANT_Byte: { byte val = (byte) input.read_u8(); constant = Constant.V_BYTE(val); break; } case WyilFileWriter.CONSTANT_Char: { char val = (char) input.read_uv(); constant = Constant.V_CHAR(val); break; } case WyilFileWriter.CONSTANT_Int: { int len = input.read_uv(); byte[] bytes = new byte[len]; input.read(bytes); BigInteger bi = new BigInteger(bytes); constant = Constant.V_INTEGER(bi); break; } case WyilFileWriter.CONSTANT_Real: { int len = input.read_uv(); byte[] bytes = new byte[len]; input.read(bytes); BigInteger num = new BigInteger(bytes); len = input.read_uv(); bytes = new byte[len]; input.read(bytes); BigInteger den = new BigInteger(bytes); BigRational br = new BigRational(num, den); constant = Constant.V_RATIONAL(br); break; } case WyilFileWriter.CONSTANT_String: { int index = input.read_uv(); constant = Constant.V_STRING(stringPool[index]); break; } case WyilFileWriter.CONSTANT_List: { int len = input.read_uv(); ArrayList<Constant> values = new ArrayList<Constant>(); for (int j = 0; j != len; ++j) { int index = input.read_uv(); values.add(myConstantPool[index]); } constant = Constant.V_LIST(values); break; } case WyilFileWriter.CONSTANT_Set: { int len = input.read_uv(); ArrayList<Constant> values = new ArrayList<Constant>(); for (int j = 0; j != len; ++j) { int index = input.read_uv(); values.add(myConstantPool[index]); } constant = Constant.V_SET(values); break; } case WyilFileWriter.CONSTANT_Tuple: { int len = input.read_uv(); ArrayList<Constant> values = new ArrayList<Constant>(); for (int j = 0; j != len; ++j) { int index = input.read_uv(); values.add(myConstantPool[index]); } constant = Constant.V_TUPLE(values); break; } case WyilFileWriter.CONSTANT_Map: { int len = input.read_uv(); HashSet<Pair<Constant, Constant>> values = new HashSet<Pair<Constant, Constant>>(); for (int j = 0; j != len; ++j) { int keyIndex = input.read_uv(); int valIndex = input.read_uv(); Constant key = myConstantPool[keyIndex]; Constant val = myConstantPool[valIndex]; values.add(new Pair<Constant, Constant>(key, val)); } constant = Constant.V_MAP(values); break; } case WyilFileWriter.CONSTANT_Record: { int len = input.read_uv(); HashMap<String, Constant> tvs = new HashMap<String, Constant>(); for (int j = 0; j != len; ++j) { int fieldIndex = input.read_uv(); int constantIndex = input.read_uv(); String str = stringPool[fieldIndex]; tvs.put(str, myConstantPool[constantIndex]); } constant = Constant.V_RECORD(tvs); break; } case WyilFileWriter.CONSTANT_Function: case WyilFileWriter.CONSTANT_Method: { int typeIndex = input.read_uv(); int nameIndex = input.read_uv(); Type.FunctionOrMethod t = (Type.FunctionOrMethod) typePool[typeIndex]; NameID name = namePool[nameIndex]; constant = Constant.V_LAMBDA(name, t); break; } default: throw new RuntimeException("Unknown constant encountered in WhileyDefine: " + code); } myConstantPool[i] = constant; } constantPool = myConstantPool; }
private Constant minus_compute(Constant c) { return Constant.create(-c.intValue()); }