Javadoc updates.

Changed the broken obfuscator/modules classes so that at least javadoc
runs cleanly.


git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@1349 379699f6-c40d-0410-875b-85095c16579e
master
hoenicke 24 years ago
parent 2d1bb14f08
commit d5a0591d1f
  1. 269
      jode/src/net/sf/jode/bytecode/ClassInfo.java
  2. 7
      jode/src/net/sf/jode/obfuscator/modules/LocalizeFieldTransformer.java
  3. 144
      jode/src/net/sf/jode/obfuscator/modules/RemovePopAnalyzer.java

@ -47,27 +47,42 @@ import java.lang.reflect.Field;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
/** /**
* Accesses, creates or modifies java bytecode classes or interfaces. * Represents a class or interface. It can't be used for primitive
* This class represents a class or interface, it can't be used for * or array types. Every class/interface is associated with a class
* primitive or array types. Every class/interface is associated with * path, which is used to load the class and its dependent classes.
* a class path, which is used to load the class in memory.
* *
* <h3>Creating a class</h3> * <h3>ClassInfo and ClassPath</h3>
* You create a new ClassInfo, by calling {@link *
* ClassPath#getClassInfo}. The resulting ClassInfo is empty and you * Every ClassInfo instance belongs to a {@link ClassPath}. This
* now have two different possibilities to fill it with informations: * class path is used to find the class and its dependent classes,
* You load the class from its classpath (from which it was created) * e.g. the super class. Even if you want to create a class info from
* or you build it from scratch by setting its contents with the * the scratch you have to associate it with a class path, in which
* various <code>setSomething</code> methods. * the dependent classes are searched.
*
* For every class path and every class name there exists at most one
* class info object with this class name. The only exception is when
* you overwrite a loaded class, e.g. by calling setName().
* *
* <h3>Changing a class</h3> * <h3>Creating a Class</h3>
* Even if the class is already filled with information you can change * As you can see, there is no public constructor. Instead you create
* it. You can, for example, set another array of methods, change the * a new ClassInfo, by calling {@link ClassPath#getClassInfo}.
* modifiers, or rename the class. Use the various * Multiple calls of this method with the same class name result in
* <code>setSomething</code> methods. * the same object. The resulting ClassInfo is initially empty and
* you now have three different means to fill it with informations:
* You can {@link #load load} the class from its classpath (from which
* it was created), you can {@link #guess guess} the information
* (useful if the class can't be loaded), or you build it from scratch
* by setting its contents with the various <code>setSomething</code>
* methods.
*
* <h3>Changing a Class</h3>
* Whether or not the classinfo was already filled with information,
* you can change it. You can, for example, provide another array of
* methods, change the modifiers, or rename the class. Use the
* various <code>setSomething</code> methods.
* *
* <h3>The components of a class</h3> * <h3>The Components of a Class</h3>
* A class consists of several components: * A class consists of several components:
* <dl> * <dl>
* <dt>name</dt><dd> * <dt>name</dt><dd>
@ -94,21 +109,20 @@ import java.lang.reflect.Modifier;
* <dt>modifiers</dt><dd> * <dt>modifiers</dt><dd>
* There is a set of access modifiers (AKA access flags) attached to * There is a set of access modifiers (AKA access flags) attached to
* each class. They are represented as integers (bitboard) and can * each class. They are represented as integers (bitboard) and can
* be conveniently accessed via * be conveniently accessed via {@link java.lang.reflect.Modifier}.
* <code>java.lang.reflect.Modifier</code>. <br> <br> * <br>
* *
* Inner classes can have more modifiers than normal classes. To be * Inner classes can have more modifiers than normal classes, as
* backwards compatible this was implemented by Sun by having the real * they can be private, protected or static. These extended modifiers
* modifiers for inner classes at a special location, while the old * are supported, too. <br>
* location has only the modifiers that were allowed previously. *
* This package knows about this and always returns the real modifiers. * <b>TODO:</b> Check that reflection returns the extended modifiers!
* The old modifiers are checked if they match the new extended ones.<br>
* <b>TODO:</b> Check that reflection returns the new modifiers!
* </dd> * </dd>
* <dt>superclass</dt><dd> * <dt>superclass</dt><dd>
* Every class except java.lang.Object has a super class. The super class * Every class except <code>java.lang.Object</code> has a super
* is created in the same classpath as the current class. Interfaces * class. The super class is created in the same classpath as the
* always have <code>java.lang.Object</code> as their super class. * current class. Interfaces always have
* <code>java.lang.Object</code> as their super class.
* </dd> * </dd>
* <dt>interfaces</dt><dd> * <dt>interfaces</dt><dd>
* Every class (resp. interfaces) can implement (resp. extend) * Every class (resp. interfaces) can implement (resp. extend)
@ -118,61 +132,62 @@ import java.lang.reflect.Modifier;
* Fields are represented as {@link FieldInfo} objects. * Fields are represented as {@link FieldInfo} objects.
* </dd> * </dd>
* <dt>methods</dt><dd> * <dt>methods</dt><dd>
* Fields are represented as {@link MethodInfo} objects. * Methods are represented as {@link MethodInfo} objects.
* </dd> * </dd>
* <dt>method scoped</dt><dd> * <dt>method scoped</dt><dd>
* A boolean value; true if this class is an anonymous or method * A boolean value; true if this class is an anonymous or method
* scoped class. * scoped class.
* </dd> * </dd>
* <dt>outer class</dt><dd> * <dt>outer class</dt><dd>
* the class of which this class is the inner class. It returns * the class in which this class or interface was declared. It
* null for package scoped and method scoped classes. <br> * returns null for package scoped and method scoped classes.
* </dd> * </dd>
* <dt>classes</dt><dd> * <dt>classes</dt><dd>
* the inner classes which is an array of ClassInfo. This doesn't * the inner classes declared in this class. This doesn't include
* include method scoped classes.<br> * method scoped classes.
* </dd> * </dd>
* <dt>source file</dt><dd> * <dt>source file</dt><dd>
* The name of source file. The JVM uses this field when a stack * The name of source file. The JVM uses this field when a stack
* trace is produced. * trace is produced. It may be null if the class was compiled
* without debugging information.
* </dd> * </dd>
* </dl> * </dl>
* *
* <h3>inner classes</h3> * <h3>Inner Classes</h3>
* Inner classes are supported as far as the information is present in * Inner classes are supported as far as the information is present in
* the bytecode. But you can always ignore this inner information, * the bytecode. However, you can always ignore this inner
* and access inner classes by their bytecode name, * information, and access inner classes by their bytecode name,
* e.g. <code>java.util.Map$Entry</code>. There are four different types * e.g. <code>java.util.Map$Entry</code>. There are four different
* of classes: * types of classes:
* <dl> * <dl>
* <dt>normal package scoped classes</dt><dd> * <dt>normal package scoped classes</dt><dd>
* A class is package scoped if, and only if * A class is package scoped if, and only if
* <code>getOuterClass()</code> returns <code>null</code> and * {@link #getOuterClass()} returns <code>null</code> and
* <code>isMethodScoped()</code> returns <code>false</code>. * {@link #isMethodScoped()} returns <code>false</code>.
* </dd> * </dd>
* <dt>class scoped classes (inner classes)</dt><dd> * <dt>class scoped classes (inner classes)</dt><dd>
* A class is class scoped if, and only if * A class is class scoped if, and only if
* <code>getOuterClass()</code> returns not <code>null</code>. * {@link #getOuterClass()} returns not <code>null</code>.
* *
* The bytecode name (<code>getName()</code>) of an inner class is * The bytecode name ({@link #getName()}) of an inner class is
* in most cases of the form <code>Package.Outer$Inner</code>. But * in normally of the form <code>Package.Outer$Inner</code>. However,
* ClassInfo also supports differently named classes, as long as the * ClassInfo also supports differently named classes, as long as the
* InnerClass attribute is present. The method * InnerClass attribute is present. The method
* <code>getClassName()</code> returns the name of the inner class * {@link #getClassName()} returns the name of the inner class
* (<code>Inner</code> in the above example). * (<code>Inner</code> in the above example).
* *
* You can get all inner classes of a class with the * You can get all inner classes of a class with the
* <code>getClasses</code> method. * method {@link #getClasses}.
* </dd> * </dd>
* <dt>named method scoped classes</dt><dd> * <dt>named method scoped classes</dt><dd>
* A class is a named method scoped class if, and only if * A class is a named method scoped class if, and only if
* <code>isMethodScoped()</code> returns <code>true</code> and * {@link #isMethodScoped()} returns <code>true</code> and
* <code>getClassName()</code> returns not <code>null</code>. In * {@link #getClassName()} returns not <code>null</code>. In
* that case <code>getOuterClass()</code> returns <code>null</code>, * that case {@link #getOuterClass()} returns <code>null</code>,
* too.<br><br> * too.<br><br>
* *
* The bytecode name (<code>getName()</code>) of an method scoped class is * The bytecode name ({@link #getName()}) of a method scoped class is
* in most cases of the form <code>Package.Outer$Number$Inner</code>. But * normally of the form <code>Package.Outer$Number$Inner</code>. However,
* ClassInfo also supports differently named classes, as long as the * ClassInfo also supports differently named classes, as long as the
* InnerClass attribute is present. <br><br> * InnerClass attribute is present. <br><br>
* *
@ -182,16 +197,15 @@ import java.lang.reflect.Modifier;
* </dd> * </dd>
* <dt>anonymous classes</dt><dd> * <dt>anonymous classes</dt><dd>
* A class is an anonymous class if, and only if * A class is an anonymous class if, and only if
* <code>isMethodScoped()</code> returns <code>true</code> and * {@link #isMethodScoped()} returns <code>true</code> and
* <code>getClassName()</code> returns <code>null</code>. In that * {@link #getClassName()} returns <code>null</code>. In that
* case <code>getOuterClass()</code> returns <code>null</code>, * case {@link #getOuterClass()} returns <code>null</code>,
* too.<br><br> * too.<br><br>
* *
* The bytecode name (<code>getName()</code>) of an method scoped * The bytecode name ({@link #getName()}) of a method scoped class
* class is in most cases of the form * is normally of the form <code>Package.Outer$Number</code>.
* <code>Package.Outer$Number</code>. But ClassInfo also supports * However, ClassInfo also supports differently named classes, as
* differently named classes, as long as the InnerClass attribute is * long as the InnerClass attribute is present. <br><br>
* present. <br><br>
* *
* There's no way to get the anonymous classes of a method, except * There's no way to get the anonymous classes of a method, except
* by analyzing its instructions. And even that is error prone, since * by analyzing its instructions. And even that is error prone, since
@ -200,22 +214,21 @@ import java.lang.reflect.Modifier;
* </dl> * </dl>
* *
* <hr> * <hr>
* <h3>Open Questions</h3> * <h3>Open Question</h3>
* *
* I represent most types as <code>java/lang/String</code> (type * I represent most types as {@link String} objects (type
* signatures); this is convenient since java bytecode does the same. * signatures); this is convenient since java bytecode does the same.
* On the other hand a class type should be represented as * On the other hand a class type should be represented as
* <code>jode/bytecode/ClassInfo</code> class. There should be a * {@link ClassInfo} object. There is a method in {@link TypeSignature}
* method to convert to it, but I need a ClassPath for this. Should * to convert between them, which needs a class path. This is a
* the method be in ClassInfo (I don't think so), should an instance * bit difficult to use. <br>
* of TypeSignature have a ClassPath as member variable, or should
* getClassInfo() take a ClassPath parameter as it is currently?
* What about arrays, shall we support special ClassInfo's for them,
* as java.lang.Class does? I think the current solution is okay.
* <br>
* *
* @author Jochen Hoenicke * However the alternative would be to represents types as ClassInfo
*/ * and create ClassInfo objects for primitive and array types. But
* this contradicts the purpose of this class, which is to read and
* write class files. I think the current solution is okay. <br>
*
* @author Jochen Hoenicke */
public final class ClassInfo extends BinaryInfo implements Comparable { public final class ClassInfo extends BinaryInfo implements Comparable {
private static ClassPath defaultClasspath; private static ClassPath defaultClasspath;
@ -250,16 +263,15 @@ public final class ClassInfo extends BinaryInfo implements Comparable {
public static final int NONE = 0; public static final int NONE = 0;
/** /**
* This constant can be used as parameter to load. It specifies * This constant can be used as parameter to load. It specifies
* that at least the outer class information should be loaded, i.e. * that at least the outer class information should be loaded,
* the outer class, the class name. It is the * i.e. the outer class and the java class name. It is the only
* only information that is loaded recursively: It is also * information that is loaded recursively: It is also
* automatically loaded for the outer class and it is loaded for * automatically loaded for all classes that are accessed by this
* all inner and extra classes, if these fields are loaded. * class. The reason for the recursive load is simple: In java
* The reason for the recursive load is simple: In java bytecode * bytecode a class contains the outer class information for all
* a class contains the outer class information for all outer, * classes that it accesses, so we can create this information
* inner and extra classes, so we can create this information
* without the need to read the outer class. We also need this * without the need to read the outer class. We also need this
* information for outer and inner classes when writing a class. * information when writing a class.
* *
* @see #load * @see #load
*/ */
@ -355,6 +367,14 @@ public final class ClassInfo extends BinaryInfo implements Comparable {
return defaultClasspath.getClassInfo(name); return defaultClasspath.getClassInfo(name);
} }
/**
* Disable the default constructor.
* @exception InternalError always.
*/
private ClassInfo() throws InternalError {
throw new InternalError();
}
ClassInfo(String name, ClassPath classpath) { ClassInfo(String name, ClassPath classpath) {
/* Name may be null when reading class with unknown name from /* Name may be null when reading class with unknown name from
* stream. * stream.
@ -936,22 +956,21 @@ public final class ClassInfo extends BinaryInfo implements Comparable {
} }
/** /**
* Loads the contents of a class from the classpath. * Loads the contents of a class from its class path.
* @param howMuch The amount of information that should be read * @param howMuch The amount of information that should be loaded
* in, one of <code>HIERARCHY</code>, * at least, one of {@link #OUTERCLASS}, {@link #HIERARCHY}, {@link
* <code>PUBLICDECLARATIONS</code>, * #PUBLICDECLARATIONS}, {@link #DECLARATIONS}, {@link #NODEBUG},
* <code>DECLARATIONS</code>, <code>ALMOSTALL</code> * {@link #ALMOSTALL} or {@link #ALL}. Note that more information
* or <code>ALL</code>. * than requested can be loaded if this is convenient.
* @exception ClassFormatException if the file doesn't denote a * @exception ClassFormatException if the file doesn't denote a
* valid class. * valid class.
* @exception FileNotFoundException if class wasn't found in classpath. * @exception FileNotFoundException if class wasn't found in classpath.
* @exception IOException if an io exception occured. * @exception IOException if an io exception occured while reading
* @exception IllegalStateException if this ClassInfo was modified. * the class.
* @see #HIERARCHY * @exception SecurityException if a security manager prohibits loading
* @see #PUBLICDECLARATIONS * the class.
* @see #DECLARATIONS * @exception IllegalStateException if this ClassInfo was modified by
* @see #ALMOSTALL * calling one of the setSomething methods.
* @see #ALL
*/ */
public void load(int howMuch) public void load(int howMuch)
throws IOException throws IOException
@ -975,8 +994,8 @@ public final class ClassInfo extends BinaryInfo implements Comparable {
* extends java.lang.Object, implements no interfaces and has no * extends java.lang.Object, implements no interfaces and has no
* fields, methods or inner classes. * fields, methods or inner classes.
* *
* @param howMuch The amount of information that should be read, e.g. * @param howMuch The amount of information that should be read,
* <code>HIERARCHY</code>. * e.g. {@link #HIERARCHY}.
* @see #OUTERCLASS * @see #OUTERCLASS
* @see #HIERARCHY * @see #HIERARCHY
* @see #PUBLICDECLARATIONS * @see #PUBLICDECLARATIONS
@ -1035,9 +1054,11 @@ public final class ClassInfo extends BinaryInfo implements Comparable {
/** /**
* This is the counter part to load and guess. It will drop all * This is the counter part to load and guess. It will drop all
* informations bigger than "keep" and clean up the memory. * informations bigger than "keep" and clean up the memory. Note
* that drop should be used with care if more than one thread
* accesses this ClassInfo.
* @param keep tells how much info we should keep, can be * @param keep tells how much info we should keep, can be
* <code>NONE</code> or anything that <code>load</code> accepts. * {@link #NONE} or anything that <code>load</code> accepts.
* @see #load * @see #load
*/ */
public void drop(int keep) { public void drop(int keep) {
@ -1091,6 +1112,11 @@ public final class ClassInfo extends BinaryInfo implements Comparable {
return name; return name;
} }
/**
* Tells whether the information in this class was guessed by a call
* to {@link #guess}.
* @return true if the information was guessed.
*/
public boolean isGuessed() { public boolean isGuessed() {
return isGuessed; return isGuessed;
} }
@ -1142,16 +1168,37 @@ public final class ClassInfo extends BinaryInfo implements Comparable {
return interfaces; return interfaces;
} }
/**
* Gets the modifiers of this class, e.g. public or abstract. The
* information is only available if at least {@link #HIERARCHY} is
* loaded.
* @return a bitboard of the modifiers.
* @see Class#getModifiers
* @see Modifier
*/
public int getModifiers() { public int getModifiers() {
if (modifiers == -1) if (modifiers == -1)
throw new IllegalStateException("status is "+status); throw new IllegalStateException("status is "+status);
return modifiers; return modifiers;
} }
/**
* Checks whether this class info represents an interface. The
* information is only available if at least {@link #HIERARCHY} is
* loaded.
* @return true if this class info represents an interface.
*/
public boolean isInterface() { public boolean isInterface() {
return Modifier.isInterface(getModifiers()); return Modifier.isInterface(getModifiers());
} }
/**
* Searches for a field with given name and type signature.
* @param name the name of the field.
* @param typeSig the {@link TypeSignature type signature} of the
* field.
* @return the field info for the field.
*/
public FieldInfo findField(String name, String typeSig) { public FieldInfo findField(String name, String typeSig) {
if (status < PUBLICDECLARATIONS) if (status < PUBLICDECLARATIONS)
throw new IllegalStateException("status is "+status); throw new IllegalStateException("status is "+status);
@ -1162,6 +1209,13 @@ public final class ClassInfo extends BinaryInfo implements Comparable {
return null; return null;
} }
/**
* Searches for a method with given name and type signature.
* @param name the name of the method.
* @param typeSig the {@link TypeSignature type signature} of the
* method.
* @return the method info for the method.
*/
public MethodInfo findMethod(String name, String typeSig) { public MethodInfo findMethod(String name, String typeSig) {
if (status < PUBLICDECLARATIONS) if (status < PUBLICDECLARATIONS)
throw new IllegalStateException("status is "+status); throw new IllegalStateException("status is "+status);
@ -1172,12 +1226,18 @@ public final class ClassInfo extends BinaryInfo implements Comparable {
return null; return null;
} }
/**
* Gets the methods of this class.
*/
public MethodInfo[] getMethods() { public MethodInfo[] getMethods() {
if (status < PUBLICDECLARATIONS) if (status < PUBLICDECLARATIONS)
throw new IllegalStateException("status is "+status); throw new IllegalStateException("status is "+status);
return methods; return methods;
} }
/**
* Gets the fields (class and member variables) of this class.
*/
public FieldInfo[] getFields() { public FieldInfo[] getFields() {
if (status < PUBLICDECLARATIONS) if (status < PUBLICDECLARATIONS)
throw new IllegalStateException("status is "+status); throw new IllegalStateException("status is "+status);
@ -1200,7 +1260,7 @@ public final class ClassInfo extends BinaryInfo implements Comparable {
} }
/** /**
* Returns true if the class was declared inside a method. * Tells whether the class was declared inside a method.
* This needs the OUTERCLASS information loaded. * This needs the OUTERCLASS information loaded.
* @return true if this is a method scoped or an anonymous class, * @return true if this is a method scoped or an anonymous class,
* false otherwise. * false otherwise.
@ -1215,11 +1275,12 @@ public final class ClassInfo extends BinaryInfo implements Comparable {
} }
/** /**
* Returns the inner classes declared in this class. * Gets the inner classes declared in this class.
* This needs at least PUBLICDECLARATION information loaded. * This needs at least PUBLICDECLARATION information loaded.
* @return an array containing the inner classes, guaranteed != null. * @return an array containing the inner classes, guaranteed != null.
* @exception IllegalStateException if PUBLICDECLARATIONS information * @exception IllegalStateException if PUBLICDECLARATIONS information
* wasn't loaded yet. */ * wasn't loaded yet.
*/
public ClassInfo[] getClasses() { public ClassInfo[] getClasses() {
if (status < PUBLICDECLARATIONS) if (status < PUBLICDECLARATIONS)
throw new IllegalStateException("status is "+status); throw new IllegalStateException("status is "+status);
@ -1457,6 +1518,10 @@ public final class ClassInfo extends BinaryInfo implements Comparable {
return clazz == this; return clazz == this;
} }
/**
* Returns a string representation of the class. This is just the
* full qualified class name.
*/
public String toString() { public String toString() {
return name; return name;
} }

@ -26,10 +26,7 @@ import net.sf.jode.obfuscator.*;
*/ */
public class LocalizeFieldTransformer implements CodeTransformer { public class LocalizeFieldTransformer implements CodeTransformer {
public static void transformCode(BytecodeInfo bytecode) { public void transformCode(BasicBlocks bb) {
for (Instruction instr = bytecode.getFirstInstr(); /* XXX implement */
instr != null; instr = instr.nextByAddr) {
}
} }
} }

@ -186,13 +186,13 @@ public class RemovePopAnalyzer implements CodeTransformer, Opcodes {
(Instruction.forOpcode(opc_pop)); //DCABD< (Instruction.forOpcode(opc_pop)); //DCABD<
newInstructions.addFirst newInstructions.addFirst
(Instruction.forOpcode(opc_dup2_x2)); //DCABDC< (Instruction.forOpcode(opc_dup2_x2)); //DCABDC<
swappedBeforeDup = !swappedBeforeDup //ABDC< swappedBeforeDup = !swappedBeforeDup; //ABDC<
} }
if (swapBeforeDup) if (swapBeforeDup)
newInstructions.addFirst newInstructions.addFirst
(Instruction.forOpcode(opc_swap)); (Instruction.forOpcode(opc_swap));
return newPopped return newPopped;
} }
/** /**
@ -369,7 +369,7 @@ public class RemovePopAnalyzer implements CodeTransformer, Opcodes {
blocks[i].setCode((Instruction[]) newInstructions blocks[i].setCode((Instruction[]) newInstructions
.toArray(new Instruction[newInstructions.size()]), .toArray(new Instruction[newInstructions.size()]),
blocks[i].getSuccs()); blocks[i].getSuccs());
return poppedEntries return poppedEntries;
} }
/** /**
@ -399,143 +399,7 @@ public class RemovePopAnalyzer implements CodeTransformer, Opcodes {
Instruction instr = oldInstrs[--instrNr]; Instruction instr = oldInstrs[--instrNr];
instr.getStackPopPush(poppush); instr.getStackPopPush(poppush);
for (stackDepth /* XXX handle pops inside a opc_dup */
/* Check if this instr pushes a popped Entry. */
boolean pops_a_popped = false;
boolean pops_all_popped = true;
for (int j=0; j < poppush[1]; j++) {
if (poppedEntries.get(j))
push_a_popped = true;
else
push_all_popped = false;
}
if (!push_a_popped) {
// Normal case:
// add the instruction and adjust stack depth.
newInstructions.addFirst(instr);
stackDepth += poppush[0] - poppush[1];
continue;
}
/* We push an entry, that gets popped later */
int opcode = instr.getOpcode();
switch (opcode) {
case opc_dup:
case opc_dup_x1:
case opc_dup_x2:
case opc_dup2:
case opc_dup2_x1:
case opc_dup2_x2: {
int popped = 0;
for (int j = poppush[1] ; j > 0; j--) {
popped <<= 1;
if (poppedEntries.get(--stackDepth)) {
popped |= 1;
poppedEntries.clear(stackDepth);
}
}
popped = movePopsThroughDup(opcode, newInstructions,
popped);
for (int j=0; j < poppush[1]; j++) {
if ((popped & 1) != 0)
poppedEntries.set(stackDepth);
stackDepth++;
popped >>=1;
}
break;
}
case opc_swap:
if (!push_all_popped) {
// swap the popped status
if (poppedEntries.get(stackDepth - 1)) {
poppedEntries.clear(stackDepth - 1);
poppedEntries.set(stackDepth - 2);
} else {
poppedEntries.set(stackDepth - 1);
poppedEntries.clear(stackDepth - 2);
}
}
case opc_ldc2_w:
case opc_lload: case opc_dload:
case opc_i2l: case opc_i2d:
case opc_f2l: case opc_f2d:
case opc_ldc:
case opc_iload: case opc_fload: case opc_aload:
case opc_new:
case opc_lneg: case opc_dneg:
case opc_l2d: case opc_d2l:
case opc_laload: case opc_daload:
case opc_ineg: case opc_fneg:
case opc_i2f: case opc_f2i:
case opc_i2b: case opc_i2c: case opc_i2s:
case opc_newarray: case opc_anewarray:
case opc_arraylength:
case opc_instanceof:
case opc_lshl: case opc_lshr: case opc_lushr:
case opc_iaload: case opc_faload: case opc_aaload:
case opc_baload: case opc_caload: case opc_saload:
case opc_iadd: case opc_fadd:
case opc_isub: case opc_fsub:
case opc_imul: case opc_fmul:
case opc_idiv: case opc_fdiv:
case opc_irem: case opc_frem:
case opc_iand: case opc_ior : case opc_ixor:
case opc_ishl: case opc_ishr: case opc_iushr:
case opc_fcmpl: case opc_fcmpg:
case opc_l2i: case opc_l2f:
case opc_d2i: case opc_d2f:
case opc_ladd: case opc_dadd:
case opc_lsub: case opc_dsub:
case opc_lmul: case opc_dmul:
case opc_ldiv: case opc_ddiv:
case opc_lrem: case opc_drem:
case opc_land: case opc_lor : case opc_lxor:
case opc_lcmp:
case opc_dcmpl: case opc_dcmpg:
case opc_getstatic:
case opc_getfield:
case opc_multianewarray:
/* The simple instructions, that can be removed. */
if (!push_all_popped)
throw new InternalError("pop half of a long");
if (poppush[0] < poppush[1]) {
for (int j=0; j < poppush[0] - poppush[1]; j++)
poppedEntries.set(stackDepth++);
} else if (poppush[0] < poppush[1]) {
for (int j=0; j < poppush[0] - poppush[1]; j++)
poppedEntries.clear(--stackDepth);
}
case opc_invokevirtual:
case opc_invokespecial:
case opc_invokestatic:
case opc_invokeinterface:
case opc_checkcast:
/* These instructions can't be removed, since
* they have side effects.
*/
if (!push_all_popped)
throw new InternalError("pop half of a long");
if (poppush[1] == 1) {
poppedEntries.clear(--stackDepth);
newInstructions
.addFirst(Instruction.forOpcode(opc_pop));
} else {
poppedEntries.clear(--stackDepth);
poppedEntries.clear(--stackDepth);
newInstructions
.addFirst(Instruction.forOpcode(opc_pop2));
}
newInstructions.addFirst(instr);
default:
throw new InternalError("Unexpected opcode!");
}
} }
block.setCode((Instruction[]) newInstructions block.setCode((Instruction[]) newInstructions
.toArray(new Instruction[newInstructions.size()]), .toArray(new Instruction[newInstructions.size()]),

Loading…
Cancel
Save