Some copyright/documentation updates

* src/net/sf/jode/bytecode/BinaryInfo.java (ACC_*): added
constants describing modifier attributes.
* src/net/sf/jode/bytecode/BasicBlockReader.java
(convertHandlers): remove empty handlers.
(readCode): merge adjacent try-blocks (splitted by javac-1.4
return rule).
* src/net/sf/jode/bytecode/FieldInfo.java (syntheticFlag):
removed, use modifier and ACC_SYNTHETIC (new in java 5) instead.
Changed all usages.  When writing it currently writes out both
old and new synthetic format.
(getSignature): New method to return full generic signature.
* src/net/sf/jode/bytecode/MethodInfo.java
(syntheticFlag, getSignature): likewise.
* src/net/sf/jode/bytecode/ClassInfo.java (getSignature):
new method to return full generic signature.
* src/net/sf/jode/decompiler/MethodAnalyzer.java (skipWriting):
Skip java 5 bridge methods.
* src/net/sf/jode/expr/InvokeOperator.java (getClassAnalyzer):
Check for null callee.
* src/net/sf/jode/expr/FlowBlock.java (analyze): New order for
T1,T2 analysis:  Do not do T1 analysis when the block has more
than one real successor and the next block can be easily merged.
See comment for more information.


git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@1383 379699f6-c40d-0410-875b-85095c16579e
master
hoenicke 20 years ago
parent 033d9d57e5
commit 487a4b49d9
  1. 26
      jode/ChangeLog
  2. 6
      jode/build.xml
  3. 2
      jode/src/net/sf/jode/GlobalOptions.java
  4. 41
      jode/src/net/sf/jode/bytecode/BasicBlockReader.java
  5. 82
      jode/src/net/sf/jode/bytecode/BinaryInfo.java
  6. 30
      jode/src/net/sf/jode/bytecode/ClassInfo.java
  7. 6
      jode/src/net/sf/jode/bytecode/ClassPath.java
  8. 29
      jode/src/net/sf/jode/bytecode/FieldInfo.java
  9. 29
      jode/src/net/sf/jode/bytecode/MethodInfo.java
  10. 17
      jode/src/net/sf/jode/bytecode/TypeSignature.java
  11. 4
      jode/src/net/sf/jode/decompiler/MethodAnalyzer.java
  12. 2
      jode/src/net/sf/jode/expr/InvokeOperator.java
  13. 79
      jode/src/net/sf/jode/flow/FlowBlock.java

@ -1,3 +1,29 @@
2004-08-06 Jochen Hoenicke <hoenicke@marge.Informatik.Uni-Oldenburg.DE>
* src/net/sf/jode/bytecode/BinaryInfo.java (ACC_*): added
constants describing modifier attributes.
* src/net/sf/jode/bytecode/BasicBlockReader.java
(convertHandlers): remove empty handlers.
(readCode): merge adjacent try-blocks (splitted by javac-1.4
return rule).
* src/net/sf/jode/bytecode/FieldInfo.java (syntheticFlag):
removed, use modifier and ACC_SYNTHETIC (new in java 5) instead.
Changed all usages. When writing it currently writes out both
old and new synthetic format.
(getSignature): New method to return full generic signature.
* src/net/sf/jode/bytecode/MethodInfo.java
(syntheticFlag, getSignature): likewise.
* src/net/sf/jode/bytecode/ClassInfo.java (getSignature):
New method to return full generic signature.
* src/net/sf/jode/decompiler/MethodAnalyzer.java (skipWriting):
Skip java 5 bridge methods.
* src/net/sf/jode/expr/InvokeOperator.java (getClassAnalyzer):
Check for null callee.
* src/net/sf/jode/expr/FlowBlock.java (analyze): New order for
T1,T2 analysis: Do not do T1 analysis when the block has more
than one real successor and the next block can be easily merged.
See comment for more information.
2004-08-05 Jochen Hoenicke <hoenicke@marge.Informatik.Uni-Oldenburg.DE>
* build.xml: replace execon with apply.

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Jakarta-Ant build file for jode, Copyright (C) 1999-2001 Jochen Hoenicke.
<!-- Jakarta-Ant build file for jode, Copyright (C) 1999-2004 Jochen Hoenicke.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -146,6 +146,7 @@
<mkdir dir="${build}"/>
<javac srcdir="${src}"
destdir="${build}"
debug="true"
classpathref="project.classpath"
deprecation="on">
<exclude name="net/sf/jode/obfuscator/modules/RemovePopAnalyzer.java"/>
@ -272,7 +273,7 @@
windowtitle="Jode ${version} API Specification"
header='&lt;b&gt;&lt;a href="http://jode.sourceforge.net/"&gt;Jode&lt;/a&gt; ${version}&lt;/b&gt;&lt;br&gt;&lt;font size="-2"&gt;Build ${date}&lt;/font&gt;'
overview="${src}/net/sf/jode/overview.html"
bottom='Copyright &amp;copy; 1998-2001 by Jochen Hoenicke.'
bottom='Copyright &amp;copy; 1998-2004 by Jochen Hoenicke.'
sourcepath="${src}"
destdir="${api.doc}"
use="yes">
@ -298,6 +299,7 @@
<mkdir dir="${test.build}"/>
<javac srcdir="${test.src}"
destdir="${test.build}"
debug="true"
classpathref="project.classpath"
classpath="${build}"
deprecation="on">

@ -25,7 +25,7 @@ public class GlobalOptions {
public final static String version = "@VERSION@";
public final static String email = "jochen@gnu.org";
public final static String copyright =
"Jode (c) 1998-2001 Jochen Hoenicke <"+email+">";
"Jode (c) 1998-2004 Jochen Hoenicke <"+email+">";
public final static String URL = "http://jode.sourceforge.net/";
public static PrintWriter err = new PrintWriter(System.err, true);

@ -224,25 +224,27 @@ class BasicBlockReader implements Opcodes {
private Handler[] convertHandlers() {
int newCount = 0;
for (int i=0; i < handlers.length; i++) {
while (handlers[i].start < handlers[i].end
&& infos[handlers[i].start].blockNr == -1)
handlers[i].start = infos[handlers[i].start].nextAddr;
if (handlers[i].start == handlers[i].end)
continue;
while (handlers[i].end < infos.length
&& infos[handlers[i].end].blockNr == -1)
handlers[i].end = infos[handlers[i].end].nextAddr;
if ((infos[handlers[i].catcher].flags & IS_REACHABLE) != 0)
newCount++;
}
Handler[] newHandlers = new Handler[newCount];
int ptr = 0;
for (int i=0; i<handlers.length; i++) {
int start = handlers[i].start;
while (infos[start].blockNr == -1)
start = infos[start].nextAddr;
int end = handlers[i].end;
while (end < infos.length
&& infos[end].blockNr == -1)
end = infos[end].nextAddr;
int endBlock = end < infos.length
? infos[end].blockNr : blocks.length;
if ((infos[handlers[i].catcher].flags & IS_REACHABLE) != 0) {
for (int i=0; i<handlers.length; i++) {
if (handlers[i].start < handlers[i].end
&& (infos[handlers[i].catcher].flags & IS_REACHABLE) != 0) {
int endBlock = handlers[i].end < infos.length
? infos[handlers[i].end].blockNr : blocks.length;
newHandlers[ptr++] = new Handler
(blocks[infos[start].blockNr],
(blocks[infos[handlers[i].start].blockNr],
blocks[endBlock - 1],
getSuccBlock(handlers[i].catcher),
handlers[i].type);
@ -856,6 +858,17 @@ class BasicBlockReader implements Opcodes {
handlers[i].type = (index == 0) ? null
: cp.getClassName(index);
if (i > 0 && handlers[i].start == handlers[i-1].end
&& handlers[i].catcher == handlers[i-1].catcher
&& handlers[i].type == handlers[i-1].type) {
/* Javac 1.4 splits handlers at return instruction
* (see below). We merge them together here.
*/
handlers[i-1].end = handlers[i].end;
handlersLength--;
i--;
}
if ((GlobalOptions.debuggingFlags
& GlobalOptions.DEBUG_BYTECODE) != 0)
GlobalOptions.err.println("Handler "+handlers[i].start
@ -870,6 +883,7 @@ class BasicBlockReader implements Opcodes {
*/
handlersLength--;
i--;
continue;
}
if (handlers[i].start <= handlers[i].catcher
@ -883,6 +897,7 @@ class BasicBlockReader implements Opcodes {
if (handlers[i].start == handlers[i].catcher) {
handlersLength--;
i--;
continue;
} else {
handlers[i].end = handlers[i].catcher;
}

@ -61,6 +61,79 @@ import java.util.Iterator;
* @author Jochen Hoenicke
*/
public class BinaryInfo {
/**
* The bit mask representing public modifier.
*/
public static int ACC_PUBLIC = 0x0001;
/**
* The bit mask representing private modifier.
*/
public static int ACC_PRIVATE = 0x0002;
/**
* The bit mask representing protected modifier.
*/
public static int ACC_PROTECTED = 0x0004;
/**
* The bit mask representing static modifier.
*/
public static int ACC_STATIC = 0x0008;
/**
* The bit mask representing final modifier.
*/
public static int ACC_FINAL = 0x0010;
/**
* The bit mask representing the ACC_SUPER modifier for classes.
* This is a special modifier that only has historic meaning. Every
* class should have this set.
*/
public static int ACC_SUPER = 0x0020;
/**
* The bit mask representing volatile modifier for fields.
*/
public static int ACC_VOLATILE = 0x0040;
/**
* The bit mask representing synthetic bridge method. This is
* used when a non-generic method overrides a generic method of
* super class/interface.
*/
public static int ACC_BRIDGE = 0x0040;
/**
* The bit mask representing transient fields.
*/
public static int ACC_TRANSIENT = 0x0080;
/**
* The bit mask representing varargs methods.
*/
public static int ACC_VARARGS = 0x0080;
/**
* The bit mask representing enum fields.
*/
public static int ACC_ENUM = 0x0100;
/**
* The bit mask representing native methods.
*/
public static int ACC_NATIVE = 0x0100;
/**
* The bit mask representing interfaces.
*/
public static int ACC_INTERFACE = 0x0200;
/**
* The bit mask representing abstract modifier.
*/
public static int ACC_ABSTRACT = 0x0400;
/**
* The bit mask representing annotation classes.
*/
public static int ACC_ANNOTATION = 0x0800;
/**
* The bit mask representing strictfp modifier.
*/
public static int ACC_STRICT = 0x0800;
/**
* The bit mask representing synthetic fields/methods and classes.
*/
public static int ACC_SYNTHETIC = 0x1000;
private Map unknownAttributes = null;
void skipAttributes(DataInputStream input) throws IOException {
@ -174,8 +247,8 @@ public class BinaryInfo {
/**
* Drops information from this info. Override this to drop your
* own info and don't forget to call the method of the super class.
* @param howMuch the constant that was given to the {@link
* ClassInfo#drop} function when loading this class.
* @param keep the constant representing how much information we
* should keep (see {@link ClassInfo#load}).
*/
protected void drop(int keep) {
if (keep < ClassInfo.ALL)
@ -214,13 +287,14 @@ public class BinaryInfo {
* Overwrite this method if you want to add your own attributes.
* All constants you need from the growable constant pool must
* have been previously registered by the {@link #prepareAttributes}
* method.</p>
* method. This method must not add new constants to the pool</p>
*
* First call the method of the super class. Afterwrites write
* each of your own attributes including the attribute header
* (name and length entry).
*
* @param gcp The growable constant pool, which is not growable anymore.
* @param constantPool The growable constant pool, which is not
* growable anymore (see above).
* @param output the data output stream. You must write exactly
* as many bytes to it as you have told with the {@link
* #getAttributeSize} method.

@ -128,6 +128,9 @@ import java.lang.reflect.Modifier;
* Every class (resp. interfaces) can implement (resp. extend)
* zero or more interfaces.
* </dd>
* <dt>signature</dt><dd>The classes super class and interfaces with
* template information.</dd>
*
* <dt>fields</dt><dd>
* Fields are represented as {@link FieldInfo} objects.
* </dd>
@ -569,13 +572,13 @@ public final class ClassInfo extends BinaryInfo implements Comparable {
} else if (howMuch >= ClassInfo.OUTERCLASS
&& name.equals("InnerClasses")) {
readInnerClassesAttribute(length, cp, input);
} else if (name.equals("Signature")) {
signature = cp.getUTF8(input.readUnsignedShort());
} else if (name.equals("Deprecated")) {
deprecatedFlag = true;
if (length != 0)
throw new ClassFormatException
("Deprecated attribute has wrong length");
} else if (name.equals("Signature")) {
signature = cp.getUTF8(input.readUnsignedShort());
} else
super.readAttribute(name, length, cp, input, howMuch);
}
@ -1189,13 +1192,34 @@ public final class ClassInfo extends BinaryInfo implements Comparable {
return interfaces;
}
/**
* Gets the type signature including template information of the class.
* <b>WARNING:</b> This field may disappear and merged into getType later.
* @return the type signature.
* @see TypeSignature
*/
public String getSignature() {
if (status < HIERARCHY)
throw new IllegalStateException("status is "+status);
if (signature != null)
return signature;
StringBuffer sb = new StringBuffer();
sb.append('L').append(superclass.getName().replace('.','/'))
.append(";");
for (int i = 0; i < interfaces.length; i++) {
sb.append('L').append(interfaces[i].getName().replace('.','/'))
.append(";");
}
return sb.toString();
}
/**
* 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
* @see BinaryInfo#ACC_PUBLIC ACC_* fields in BinaryInfo
*/
public int getModifiers() {
if (modifiers == -1)

@ -518,7 +518,7 @@ public class ClassPath {
* description for more information, which kind of paths are
* supported. When a class or a file is not found in the class
* path the fallback is used.
* @param path An array of paths.
* @param paths An array of paths.
* @param fallback The fallback classpath.
*/
public ClassPath(String[] paths, ClassPath fallback) {
@ -530,7 +530,7 @@ public class ClassPath {
* Creates a new class path for the given path. See the class
* description for more information, which kind of paths are
* supported.
* @param path An array of paths.
* @param paths An array of paths.
*/
public ClassPath(String[] paths) {
initPath(paths);
@ -971,7 +971,7 @@ public class ClassPath {
/**
* Get a list of all classes and packages in the given package.
* @param package a dot-separated package name.
* @param packageName a dot-separated package name.
* @return An enumeration with all class/subpackages in the given
* package. If package doesn't denote a package it returns null.
*/

@ -37,6 +37,9 @@ import java.lang.Comparable;
* <dt>type</dt><dd>The field's {@link TypeSignature type signature}
* in bytecode format.</dd>
*
* <dt>signature</dt><dd>The field's {@link TypeSignature type signature}
* in bytecode format including template information.</dd>
*
* <dt>modifiers</dt><dd>The modifiers of the field like private, public etc.
* These are created by or-ing the constants {@link Modifier#PUBLIC},
* {@link Modifier#PRIVATE}, {@link Modifier#PROTECTED},
@ -65,7 +68,6 @@ public final class FieldInfo extends BinaryInfo implements Comparable {
String typeSig;
Object constant;
boolean syntheticFlag;
boolean deprecatedFlag;
/**
* The type signature that also contains template information.
@ -104,7 +106,7 @@ public final class FieldInfo extends BinaryInfo implements Comparable {
int index = input.readUnsignedShort();
constant = cp.getConstant(index);
} else if (name.equals("Synthetic")) {
syntheticFlag = true;
modifier |= ACC_SYNTHETIC;
if (length != 0)
throw new ClassFormatException
("Synthetic attribute has wrong length");
@ -140,7 +142,7 @@ public final class FieldInfo extends BinaryInfo implements Comparable {
else
gcp.putConstant(constant);
}
if (syntheticFlag)
if (isSynthetic())
gcp.putUTF8("Synthetic");
if (deprecatedFlag)
gcp.putUTF8("Deprecated");
@ -151,7 +153,7 @@ public final class FieldInfo extends BinaryInfo implements Comparable {
int count = super.getAttributeCount();
if (constant != null)
count++;
if (syntheticFlag)
if (isSynthetic())
count++;
if (deprecatedFlag)
count++;
@ -173,7 +175,7 @@ public final class FieldInfo extends BinaryInfo implements Comparable {
index = gcp.putConstant(constant);
output.writeShort(index);
}
if (syntheticFlag) {
if (isSynthetic()) {
output.writeShort(gcp.putUTF8("Synthetic"));
output.writeInt(0);
}
@ -214,6 +216,16 @@ public final class FieldInfo extends BinaryInfo implements Comparable {
return typeSig;
}
/**
* Gets the type signature including template information of the field.
* <b>WARNING:</b> This field may disappear and merged into getType later.
* @return the type signature.
* @see TypeSignature
*/
public String getSignature() {
return signature != null ? signature : typeSig;
}
/**
* Gets the modifier of the field.
* @return the modifiers.
@ -228,7 +240,7 @@ public final class FieldInfo extends BinaryInfo implements Comparable {
* @return true if the field is synthetic.
*/
public boolean isSynthetic() {
return syntheticFlag;
return (modifier & ACC_SYNTHETIC) != 0;
}
/**
@ -277,7 +289,10 @@ public final class FieldInfo extends BinaryInfo implements Comparable {
}
public void setSynthetic(boolean flag) {
syntheticFlag = flag;
if (flag)
modifier |= ACC_SYNTHETIC;
else
modifier &= ~ACC_SYNTHETIC;
}
public void setDeprecated(boolean flag) {

@ -37,6 +37,9 @@ import java.lang.Comparable;
* <dt>type</dt><dd>The method's {@link TypeSignature type signature}
* in bytecode format.</dd>
*
* <dt>signature</dt><dd>The method's {@link TypeSignature type signature}
* in bytecode format including template information.</dd>
*
* <dt>modifiers</dt><dd>The modifiers of the field like private, public etc.
* These are created by or-ing the constants {@link Modifier#PUBLIC},
* {@link Modifier#PRIVATE}, {@link Modifier#PROTECTED},
@ -69,7 +72,6 @@ public final class MethodInfo extends BinaryInfo implements Comparable {
BasicBlocks basicblocks;
String[] exceptions;
boolean syntheticFlag;
boolean deprecatedFlag;
/**
* The type signature that also contains template information.
@ -101,7 +103,7 @@ public final class MethodInfo extends BinaryInfo implements Comparable {
throw new ClassFormatException
("Exceptions attribute has wrong length");
} else if (name.equals("Synthetic")) {
syntheticFlag = true;
modifier |= ACC_SYNTHETIC;
if (length != 0)
throw new ClassFormatException
("Synthetic attribute has wrong length");
@ -141,7 +143,7 @@ public final class MethodInfo extends BinaryInfo implements Comparable {
for (int i = 0; i < exceptions.length; i++)
gcp.putClassName(exceptions[i]);
}
if (syntheticFlag)
if (isSynthetic())
gcp.putUTF8("Synthetic");
if (deprecatedFlag)
gcp.putUTF8("Deprecated");
@ -154,7 +156,7 @@ public final class MethodInfo extends BinaryInfo implements Comparable {
count++;
if (exceptions != null)
count++;
if (syntheticFlag)
if (isSynthetic())
count++;
if (deprecatedFlag)
count++;
@ -177,7 +179,7 @@ public final class MethodInfo extends BinaryInfo implements Comparable {
for (int i = 0; i < count; i++)
output.writeShort(gcp.putClassName(exceptions[i]));
}
if (syntheticFlag) {
if (isSynthetic()) {
output.writeShort(gcp.putUTF8("Synthetic"));
output.writeInt(0);
}
@ -213,6 +215,16 @@ public final class MethodInfo extends BinaryInfo implements Comparable {
return typeSig;
}
/**
* Gets the type signature including template information of the method.
* <b>WARNING:</b> This field may disappear and merged into getType later.
* @return the type signature.
* @see TypeSignature
*/
public String getSignature() {
return signature != null ? signature : typeSig;
}
public int getModifiers() {
return modifier;
}
@ -226,7 +238,7 @@ public final class MethodInfo extends BinaryInfo implements Comparable {
}
public boolean isSynthetic() {
return syntheticFlag;
return (modifier & ACC_SYNTHETIC) != 0;
}
public boolean isDeprecated() {
@ -254,7 +266,10 @@ public final class MethodInfo extends BinaryInfo implements Comparable {
}
public void setSynthetic(boolean flag) {
syntheticFlag = flag;
if (flag)
modifier |= ACC_SYNTHETIC;
else
modifier &= ~ACC_SYNTHETIC;
}
public void setDeprecated(boolean flag) {

@ -28,7 +28,9 @@ import net.sf.jode.util.UnifyHash;
* Primitive types have a one letter type signature. Type signature
* of classes contains the class name. Type signatures for arrays and
* methods are recursively build from the type signatures of their
* elements. <br>
* elements. <br> Since java 5 there is a new class of type
* signatures supporting generics. These can be accessed with the
* getSignature methods of ClassInfo, MethodInfo and FieldInfo.
*
* Here are a few examples:
* <table><tr><th>type signature</th><th>Java type</th></tr>
@ -49,8 +51,17 @@ import net.sf.jode.util.UnifyHash;
* <tr><td><code>()I</code></td>
* <td> method without arguments
* and <code>int</code> return type.</td></tr>
* <tr><td colspan="2"><code>&lt;E:Ljava/lang/Object;&gt;Ljava/lang/Object;Ljava/util/Collection&lt;TE;&gt;;</code></td>
* </tr><tr><td></td>
* <td> generic class over &lt;E extends Object&gt; extending
* Object and implementing Collections&lt;E&gt;</td></tr>
* <tr><td colspan="2"><code>&lt;T:Ljava/lang/Object;&gt;([TT;)[TT;</code></td>
* </tr><tr><td></td>
* <td> generic method over &lt;T extends Object&gt; taking an
* array of T as parameters and returning an array of T.</td></tr>
* </table>
*
*
* @author Jochen Hoenicke
*/
public class TypeSignature {
@ -359,7 +370,7 @@ public class TypeSignature {
/**
* Checks whether a given type signature is a valid (not method)
* type signature. Throws an exception otherwise.
* @param typeSig the type signature.
* @param typesig the type signature.
* @exception NullPointerException if typeSig is null.
* @exception IllegalArgumentException if typeSig is not a valid
* type signature or if it's a method type signature.
@ -380,7 +391,7 @@ public class TypeSignature {
/**
* Checks whether a given type signature is a valid method
* type signature. Throws an exception otherwise.
* @param typeSig the type signature.
* @param typesig the type signature.
* @exception NullPointerException if typeSig is null.
* @exception IllegalArgumentException if typeSig is not a valid
* method type signature.

@ -688,6 +688,10 @@ public class MethodAnalyzer implements Scope, ClassDeclarer {
* @return true, iff it shouldn't be written to the source code.
*/
public boolean skipWriting() {
if (isSynthetic()
&& (minfo.getModifiers() & 0x0040 /*ACC_BRIDGE*/) != 0)
return true;
if (synth != null) {
// We don't need this class anymore (hopefully?)
if (synth.getKind() == synth.GETCLASS)

@ -314,6 +314,8 @@ public final class InvokeOperator extends Operator
* inside the same base class as the caller class, null otherwise.
*/
private ClassAnalyzer getClassAnalyzer(ClassInfo callee) {
if (callee == null)
return null;
if ((Options.options &
(Options.OPTION_ANON | Options.OPTION_INNER)) == 0)
return null;

@ -820,7 +820,9 @@ public class FlowBlock {
/* The special start marker */
continue;
if (!pred.successors.containsKey(this))
throw new InternalError("Inconsistency");
throw new InternalError
("Inconsistency: "+pred.getLabel()+" not in "
+this.getLabel()+".successors");
}
StructuredBlock last = lastModified;
@ -829,41 +831,51 @@ public class FlowBlock {
|| last.outer instanceof FinallyBlock)
last = last.outer;
if (last.outer != null)
throw new InternalError("Inconsistency");
throw new InternalError
("Inconsistency: last "+lastModified
+" surrounded by unexpected structure");
Iterator iter = successors.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry entry = (Map.Entry) iter.next();
FlowBlock dest = (FlowBlock) entry.getKey();
if (dest.predecessors.contains(this) == (dest == END_OF_METHOD))
throw new InternalError("Inconsistency");
throw new InternalError
("Inconsistency: dest "+dest.getLabel()
+" doesn't contain this predecessor");
Jump jumps = ((SuccessorInfo) entry.getValue()).jumps;
if (jumps == null)
throw new InternalError("Inconsistency");
throw new InternalError("Inconsistency: no jumps for "
+dest.getLabel());
for (; jumps != null; jumps = jumps.next) {
if (jumps.destination != dest)
throw new InternalError("Inconsistency");
throw new InternalError("Inconsistency:" +jumps
+ "doesn't point to "
+dest.getLabel());
if (jumps.prev == null
|| jumps.prev.flowBlock != this
|| jumps.prev.jump != jumps)
throw new InternalError("Inconsistency");
throw new InternalError("Inconsistency in" +jumps);
prev_loop:
for (StructuredBlock prev = jumps.prev; prev != block;
prev = prev.outer) {
if (prev.outer == null)
throw new RuntimeException("Inconsistency");
throw new InternalError("Inconsistency: " +prev
+" not in flowblock");
StructuredBlock[] blocks = prev.outer.getSubBlocks();
int i;
for (i=0; i<blocks.length; i++)
if (blocks[i] == prev)
continue prev_loop;
throw new InternalError("Inconsistency");
throw new InternalError("Inconsistency: " +prev
+" not in its outer block "
+prev.outer);
}
}
}
@ -1357,18 +1369,45 @@ public class FlowBlock {
changed |= analyzeSwitch(start, end);
}
if (doT1(start, end)) {
if ((GlobalOptions.debuggingFlags & GlobalOptions.DEBUG_FLOW) != 0)
GlobalOptions.err.println("after T1: "+this);
/* T1 transformation succeeded. This may
* make another T2 analysis in the previous
* block possible.
*/
/* Do T1 analysis when there is a loop, but only if:
* - the loop has only one exit (plus returns)
* - or the successor block doesn't belong to the loop.
*
* The reason for the extra checks are loops like
*
* while (x)
* ...
* if (y)
* ...
* return
*
* which would otherwise be translated to:
*
* outer: do {
* do {
* if (!x) break outer;
* ...
* } while(!y)
* ...
* return
* } while(false)
*/
if (successors.containsKey(this)
&& (!successors.containsKey(nextByCodeOrder)
|| successors.size() == 2
|| (successors.size() == 3
&& successors.containsKey(END_OF_METHOD)))
&& doT1(start, end)) {
if ((GlobalOptions.debuggingFlags & GlobalOptions.DEBUG_FLOW) != 0)
GlobalOptions.err.println("after T1: "+this);
/* T1 transformation succeeded. This may
* make another T2 analysis in the previous
* block possible.
*/
return true;
}
}
FlowBlock succ = getSuccessor(start, end);
while (true) {
@ -1443,7 +1482,7 @@ public class FlowBlock {
* The switch analyzation. This calls doSwitchT2 and doT1 on apropriate
* regions. Only blocks whose block number lies in the given block number
* range are considered and it is taken care of, that the switch
* is never leaved. <p>
* is never left. <p>
* The current flow block must contain the switch block as lastModified.
* @param start the start of the block number range.
* @param end the end of the block number range.

Loading…
Cancel
Save