declarables reworked

git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@855 379699f6-c40d-0410-875b-85095c16579e
stable
jochen 26 years ago
parent 863bb28203
commit a84ba609b9
  1. 11
      jode/jode/flow/CatchBlock.java
  2. 20
      jode/jode/flow/FlowBlock.java
  3. 7
      jode/jode/flow/IfThenElseBlock.java
  4. 25
      jode/jode/flow/InstructionBlock.java
  5. 7
      jode/jode/flow/InstructionContainer.java
  6. 21
      jode/jode/flow/LoopBlock.java
  7. 7
      jode/jode/flow/RetBlock.java
  8. 22
      jode/jode/flow/SequentialBlock.java
  9. 173
      jode/jode/flow/StructuredBlock.java
  10. 19
      jode/jode/flow/SynchronizedBlock.java

@ -24,6 +24,7 @@ import jode.expr.Expression;
import jode.expr.LocalLoadOperator; import jode.expr.LocalLoadOperator;
import jode.expr.LocalStoreOperator; import jode.expr.LocalStoreOperator;
import jode.expr.StoreInstruction; import jode.expr.StoreInstruction;
import jode.util.SimpleSet;
/** /**
* *
@ -120,10 +121,10 @@ public class CatchBlock extends StructuredBlock {
super.removePush(); super.removePush();
} }
public VariableSet getUsed() { public SimpleSet getDeclarables() {
used = new VariableSet(); SimpleSet used = new SimpleSet();
if (exceptionLocal != null) if (exceptionLocal != null)
used.addElement(exceptionLocal); used.add(exceptionLocal);
return used; return used;
} }
@ -133,7 +134,7 @@ public class CatchBlock extends StructuredBlock {
* is marked as used, but not done. * is marked as used, but not done.
* @param done The set of the already declare variables. * @param done The set of the already declare variables.
*/ */
public void makeDeclaration(VariableSet done) { public void makeDeclaration(SimpleSet done) {
super.makeDeclaration(done); super.makeDeclaration(done);
/* Normally we have to declare our exceptionLocal. This /* Normally we have to declare our exceptionLocal. This
* is automatically done in dumpSource. * is automatically done in dumpSource.
@ -142,7 +143,7 @@ public class CatchBlock extends StructuredBlock {
* this block. In that case we do a transformation. * this block. In that case we do a transformation.
*/ */
if (declare.contains(exceptionLocal)) if (declare.contains(exceptionLocal))
declare.removeElement(exceptionLocal); declare.remove(exceptionLocal);
else { else {
LocalInfo dummyLocal = new LocalInfo(); LocalInfo dummyLocal = new LocalInfo();
Expression store = new StoreInstruction Expression store = new StoreInstruction

@ -27,6 +27,7 @@ import jode.decompiler.LocalInfo;
import jode.expr.Expression; import jode.expr.Expression;
import jode.expr.CombineableOperator; import jode.expr.CombineableOperator;
import jode.util.SimpleDictionary; import jode.util.SimpleDictionary;
import jode.util.SimpleSet;
/** /**
* A flow block is the structure of which the flow graph consists. A * A flow block is the structure of which the flow graph consists. A
@ -1489,14 +1490,19 @@ public class FlowBlock {
nextByAddr.removeOnetimeLocals(); nextByAddr.removeOnetimeLocals();
} }
public void makeDeclaration(VariableSet param) { public void mergeParams(LocalInfo[] param) {
in.merge(param); VariableSet paramSet = new VariableSet(param);
in.subtract(param); in.merge(paramSet);
in.subtract(paramSet);
}
public void makeDeclaration(LocalInfo[] param) {
block.propagateUsage(); block.propagateUsage();
Enumeration enum = param.elements(); SimpleSet declared = new SimpleSet();
while (enum.hasMoreElements()) for (int i=0; i < param.length; i++) {
((LocalInfo) enum.nextElement()).guessName(); declared.add(param[i]);
block.makeDeclaration(param); }
block.makeDeclaration(declared);
} }
public void simplify() { public void simplify() {

@ -22,6 +22,7 @@ import jode.decompiler.LocalInfo;
import jode.decompiler.TabbedPrintWriter; import jode.decompiler.TabbedPrintWriter;
import jode.expr.Expression; import jode.expr.Expression;
import jode.type.Type; import jode.type.Type;
import jode.util.SimpleSet;
/** /**
* An IfThenElseBlock is the structured block representing an if * An IfThenElseBlock is the structured block representing an if
@ -131,9 +132,9 @@ public class IfThenElseBlock extends StructuredBlock {
elseBlock.removePush(); elseBlock.removePush();
} }
public VariableSet getUsed() { public SimpleSet getDeclarables() {
used = new VariableSet(); SimpleSet used = new SimpleSet();
cond.fillInGenSet(null, used); cond.fillDeclarables(used);
return used; return used;
} }

@ -24,6 +24,7 @@ import jode.decompiler.LocalInfo;
import jode.expr.Expression; import jode.expr.Expression;
import jode.expr.StoreInstruction; import jode.expr.StoreInstruction;
import jode.expr.LocalStoreOperator; import jode.expr.LocalStoreOperator;
import jode.util.SimpleSet;
/** /**
* This is the structured block for atomic instructions. * This is the structured block for atomic instructions.
@ -100,7 +101,7 @@ public class InstructionBlock extends InstructionContainer {
* variable. In that case mark this as declaration and return the * variable. In that case mark this as declaration and return the
* variable. * variable.
*/ */
public void checkDeclaration(VariableSet declareSet) { public void checkDeclaration(SimpleSet declareSet) {
if (instr instanceof StoreInstruction if (instr instanceof StoreInstruction
&& (((StoreInstruction)instr).getLValue() && (((StoreInstruction)instr).getLValue()
instanceof LocalStoreOperator)) { instanceof LocalStoreOperator)) {
@ -114,7 +115,7 @@ public class InstructionBlock extends InstructionContainer {
*/ */
isDeclaration = true; isDeclaration = true;
storeOp.getSubExpressions()[1].makeInitializer(); storeOp.getSubExpressions()[1].makeInitializer();
declareSet.removeElement(local); declareSet.remove(local);
} }
} }
} }
@ -125,7 +126,7 @@ public class InstructionBlock extends InstructionContainer {
* is marked as used, but not done. * is marked as used, but not done.
* @param done The set of the already declare variables. * @param done The set of the already declare variables.
*/ */
public void makeDeclaration(VariableSet done) { public void makeDeclaration(SimpleSet done) {
super.makeDeclaration(done); super.makeDeclaration(done);
checkDeclaration(declare); checkDeclaration(declare);
} }
@ -133,16 +134,18 @@ public class InstructionBlock extends InstructionContainer {
public void dumpInstruction(TabbedPrintWriter writer) public void dumpInstruction(TabbedPrintWriter writer)
throws java.io.IOException throws java.io.IOException
{ {
if (instr.getType() != Type.tVoid) if (isDeclaration) {
writer.print("PUSH "); StoreInstruction store = (StoreInstruction) instr;
else if (isDeclaration) {
LocalInfo local = LocalInfo local =
((LocalStoreOperator) ((StoreInstruction) instr).getLValue()) ((LocalStoreOperator) store.getLValue()).getLocalInfo();
.getLocalInfo(); local.dumpDeclaration(writer);
writer.printType(local.getType().getHint()); writer.print(" = ");
writer.print(" "); store.getSubExpressions()[1].dumpExpression(writer);
} else {
if (instr.getType() != Type.tVoid)
writer.print("PUSH ");
instr.dumpExpression(writer);
} }
instr.dumpExpression(writer);
writer.println(";"); writer.println(";");
} }
} }

@ -21,6 +21,7 @@ package jode.flow;
import jode.decompiler.LocalInfo; import jode.decompiler.LocalInfo;
import jode.expr.Expression; import jode.expr.Expression;
import jode.expr.LocalVarOperator; import jode.expr.LocalVarOperator;
import jode.util.SimpleSet;
/** /**
* This is a method for block containing a single instruction. * This is a method for block containing a single instruction.
@ -69,10 +70,10 @@ public abstract class InstructionContainer extends StructuredBlock {
instr.fillInGenSet(in, gen); instr.fillInGenSet(in, gen);
} }
public VariableSet getUsed() { public SimpleSet getDeclarables() {
used = new VariableSet(); SimpleSet used = new SimpleSet();
if (instr != null) if (instr != null)
instr.fillInGenSet(null, used); instr.fillDeclarables(used);
return used; return used;
} }

@ -26,6 +26,7 @@ import jode.expr.ConstOperator;
import jode.expr.StoreInstruction; import jode.expr.StoreInstruction;
import jode.expr.LocalStoreOperator; import jode.expr.LocalStoreOperator;
import jode.expr.CombineableOperator; import jode.expr.CombineableOperator;
import jode.util.SimpleSet;
/** /**
* This is the structured block for an Loop block. * This is the structured block for an Loop block.
@ -200,25 +201,25 @@ public class LoopBlock extends StructuredBlock implements BreakableBlock {
* Remove all variables from set, that we can declare inside the * Remove all variables from set, that we can declare inside the
* loop-block. This is the initializer for for-blocks. * loop-block. This is the initializer for for-blocks.
*/ */
public void removeLocallyDeclareable(VariableSet set) { public void removeLocallyDeclareable(SimpleSet set) {
if (type == FOR && initInstr instanceof StoreInstruction) { if (type == FOR && initInstr instanceof StoreInstruction) {
StoreInstruction storeOp = (StoreInstruction) initInstr; StoreInstruction storeOp = (StoreInstruction) initInstr;
if (storeOp.getLValue() instanceof LocalStoreOperator) { if (storeOp.getLValue() instanceof LocalStoreOperator) {
LocalInfo local = LocalInfo local =
((LocalStoreOperator) storeOp.getLValue()).getLocalInfo(); ((LocalStoreOperator) storeOp.getLValue()).getLocalInfo();
set.removeElement(local); set.remove(local);
} }
} }
} }
public VariableSet getUsed() { public SimpleSet getDeclarables() {
used = new VariableSet(); SimpleSet used = new SimpleSet();
if (type == FOR) { if (type == FOR) {
incrInstr.fillInGenSet(null, used); incrInstr.fillDeclarables(used);
if (initInstr != null) if (initInstr != null)
initInstr.fillInGenSet(null, used); initInstr.fillDeclarables(used);
} }
cond.fillInGenSet(null, used); cond.fillDeclarables(used);
return used; return used;
} }
@ -249,7 +250,7 @@ public class LoopBlock extends StructuredBlock implements BreakableBlock {
* variable. In that case mark this as declaration and return the * variable. In that case mark this as declaration and return the
* variable. * variable.
*/ */
public void checkDeclaration(VariableSet declareSet) { public void checkDeclaration(SimpleSet declareSet) {
if (initInstr instanceof StoreInstruction if (initInstr instanceof StoreInstruction
&& (((StoreInstruction)initInstr).getLValue() && (((StoreInstruction)initInstr).getLValue()
instanceof LocalStoreOperator)) { instanceof LocalStoreOperator)) {
@ -263,7 +264,7 @@ public class LoopBlock extends StructuredBlock implements BreakableBlock {
*/ */
isDeclaration = true; isDeclaration = true;
storeOp.getSubExpressions()[1].makeInitializer(); storeOp.getSubExpressions()[1].makeInitializer();
declareSet.removeElement(local); declareSet.remove(local);
} }
} }
} }
@ -274,7 +275,7 @@ public class LoopBlock extends StructuredBlock implements BreakableBlock {
* is marked as used, but not done. * is marked as used, but not done.
* @param done The set of the already declare variables. * @param done The set of the already declare variables.
*/ */
public void makeDeclaration(VariableSet done) { public void makeDeclaration(SimpleSet done) {
super.makeDeclaration(done); super.makeDeclaration(done);
if (type == FOR && initInstr != null) if (type == FOR && initInstr != null)
checkDeclaration(declare); checkDeclaration(declare);

@ -19,6 +19,7 @@
package jode.flow; package jode.flow;
import jode.decompiler.LocalInfo; import jode.decompiler.LocalInfo;
import jode.util.SimpleSet;
/** /**
* This block represents a ret instruction. A ret instruction is * This block represents a ret instruction. A ret instruction is
@ -58,9 +59,9 @@ public class RetBlock extends StructuredBlock {
return null; return null;
} }
public VariableSet getUsed() { public SimpleSet getDeclarables() {
used = new VariableSet(); SimpleSet used = new SimpleSet();
used.addElement(local); used.add(local);
return used; return used;
} }

@ -22,6 +22,7 @@ import jode.decompiler.TabbedPrintWriter;
import jode.decompiler.LocalInfo; import jode.decompiler.LocalInfo;
import jode.expr.LocalStoreOperator; import jode.expr.LocalStoreOperator;
import jode.expr.StoreInstruction; import jode.expr.StoreInstruction;
import jode.util.SimpleSet;
/** /**
* A sequential block combines exactly two structured blocks to a new * A sequential block combines exactly two structured blocks to a new
@ -167,22 +168,23 @@ public class SequentialBlock extends StructuredBlock {
* @return all locals that are used in this block or in some sub * @return all locals that are used in this block or in some sub
* block (this is <i>not</i> the used set). * block (this is <i>not</i> the used set).
*/ */
public VariableSet propagateUsage() { public SimpleSet propagateUsage() {
used = new VariableSet(); used = getDeclarables();
VariableSet allUse = new VariableSet(); SimpleSet allUse = new SimpleSet();
VariableSet childUse0 = subBlocks[0].propagateUsage(); SimpleSet childUse0 = subBlocks[0].propagateUsage();
VariableSet childUse1 = subBlocks[1].propagateUsage(); SimpleSet childUse1 = subBlocks[1].propagateUsage();
/* All variables used somewhere inside both sub blocks, are /* All variables used somewhere inside both sub blocks, are
* used in this block, too. * used in this block, too.
* Also the variables used in first block are used in this * Also the variables used in first block are used in this
* block, except when it can be declared locally. (Note that * block, except when it can be declared locally. (Note that
* subBlocks[0].used != childUse0) */ * subBlocks[0].used != childUse0) */
used.unionExact(subBlocks[0].used); used.addAll(subBlocks[0].used);
if (subBlocks[0] instanceof LoopBlock) if (subBlocks[0] instanceof LoopBlock)
((LoopBlock) subBlocks[0]).removeLocallyDeclareable(used); ((LoopBlock) subBlocks[0]).removeLocallyDeclareable(used);
used.unionExact(childUse0.intersectExact(childUse1)); allUse.addAll(childUse0);
allUse.unionExact(childUse0); allUse.addAll(childUse1);
allUse.unionExact(childUse1); childUse0.retainAll(childUse1);
used.addAll(childUse0);
return allUse; return allUse;
} }
@ -192,7 +194,7 @@ public class SequentialBlock extends StructuredBlock {
* is marked as used, but not done. * is marked as used, but not done.
* @param done The set of the already declare variables. * @param done The set of the already declare variables.
*/ */
public void makeDeclaration(VariableSet done) { public void makeDeclaration(SimpleSet done) {
super.makeDeclaration(done); super.makeDeclaration(done);
if (subBlocks[0] instanceof InstructionBlock) if (subBlocks[0] instanceof InstructionBlock)
/* An instruction block may declare a variable for us. /* An instruction block may declare a variable for us.

@ -22,6 +22,10 @@ import jode.AssertError;
import jode.GlobalOptions; import jode.GlobalOptions;
import jode.decompiler.TabbedPrintWriter; import jode.decompiler.TabbedPrintWriter;
import jode.decompiler.LocalInfo; import jode.decompiler.LocalInfo;
import jode.decompiler.Declarable;
import jode.util.SimpleSet;
import java.util.Enumeration;
/** /**
* A structured block is the building block of the source programm. * A structured block is the building block of the source programm.
@ -63,17 +67,17 @@ public abstract class StructuredBlock {
*/ */
/** /**
* The variable set containing all variables that are used in * The SimpleSet containing all Declarables that are used in this
* this block. You must set this, before calling super.propagateUsage. * block.
*/ */
VariableSet used; SimpleSet used;
/** /**
* The variable set containing all variables we must declare. * The SimpleSet containing all Declarables we must declare.
* The analyzation is done in makeDeclaration * The analyzation is done in makeDeclaration
*/ */
VariableSet declare; SimpleSet declare;
VariableSet done; SimpleSet done;
/** /**
* The surrounding structured block. If this is the outermost * The surrounding structured block. If this is the outermost
@ -339,8 +343,8 @@ public abstract class StructuredBlock {
return false; return false;
} }
public VariableSet getUsed() { public SimpleSet getDeclarables() {
return new VariableSet(); return new SimpleSet();
} }
/** /**
@ -351,17 +355,21 @@ public abstract class StructuredBlock {
* *
* @return all locals that are used in this block or in some sub * @return all locals that are used in this block or in some sub
* block (this is <i>not</i> the used set). */ * block (this is <i>not</i> the used set). */
public VariableSet propagateUsage() { public SimpleSet propagateUsage() {
used = getUsed(); used = getDeclarables();
StructuredBlock[] subs = getSubBlocks(); StructuredBlock[] subs = getSubBlocks();
VariableSet allUse = (VariableSet) used.clone(); SimpleSet allUse = (SimpleSet) used.clone();
for (int i=0; i<subs.length; i++) { for (int i=0; i<subs.length; i++) {
VariableSet childUse = subs[i].propagateUsage(); SimpleSet childUse = subs[i].propagateUsage();
/* All variables used in more than one sub blocks, are /* All variables used in more than one sub blocks, are
* used in this block, too. * used in this block, too.
*/ */
used.unionExact(allUse.intersectExact(childUse)); Enumeration enum = childUse.elements();
allUse.unionExact(childUse); SimpleSet intersection = new SimpleSet();
intersection.addAll(childUse);
intersection.retainAll(allUse);
used.addAll(intersection);
allUse.addAll(childUse);
} }
return allUse; return allUse;
} }
@ -432,72 +440,84 @@ public abstract class StructuredBlock {
* *
* @param done The set of the already declare variables. * @param done The set of the already declare variables.
*/ */
public void makeDeclaration(VariableSet done) { public void makeDeclaration(SimpleSet done) {
this.done = (VariableSet) done.clone(); // System.err.println("makeDeclaration: done = "+done);
declare = new VariableSet(); this.done = (SimpleSet) done.clone();
declare = new SimpleSet();
java.util.Enumeration enum = used.elements(); java.util.Enumeration enum = used.elements();
// System.err.println("makeDeclaration: used = "+used);
next_used: next_used:
while (enum.hasMoreElements()) { while (enum.hasMoreElements()) {
LocalInfo local = (LocalInfo) enum.nextElement(); Declarable declarable = (Declarable) enum.nextElement();
/* First generate the names for the locals, since this may // Check if this is already declared.
* also change their types, if they are in the local if (done.contains(declarable))
* variable table. continue next_used;
*/
String localName = local.guessName(); if (declarable instanceof LocalInfo) {
LocalInfo local = (LocalInfo) declarable;
int size = done.size();
// Check if this local is already declared. /* First generate the names for the locals, since this may
for (int i=0; i< size; i++) { * also change their types, if they are in the local
LocalInfo prevLocal = done.elementAt(i); * variable table.
if (prevLocal.equals(local)) */
continue next_used; String localName = local.guessName();
}
// Merge with all locals in this block, that use the same
// Merge with all locals in this block, that use the same // slot and have compatible types and names.
// slot and have compatible types and names. Enumeration doneEnum = done.elements();
for (int i=0; i< size; i++) { while (doneEnum.hasMoreElements()) {
LocalInfo prevLocal = done.elementAt(i); Declarable previous = (Declarable) doneEnum.nextElement();
if (prevLocal.getSlot() == local.getSlot()) { if (!(previous instanceof LocalInfo))
continue;
/* XXX - I have to think about this... LocalInfo prevLocal = (LocalInfo) previous;
* there may be a case where this leads to type errors. if (prevLocal.getSlot() == local.getSlot()) {
* TODO: Give a formal proof ;-)
* One bad thing that may happen is that the name /* XXX - I have to think about this...
* of prevLocal (it has already a name) doesn't match * there may be a case where this leads to type errors.
* the intersected type. * TODO: Give a formal proof ;-)
* * One bad thing that may happen is that the name
* We don't want to merge variables, whose names are * of prevLocal (it has already a name) doesn't match
* not generated by us and differ. * the intersected type.
* *
* And don't merge "this" with any other variable * We don't want to merge variables, whose names
* since it mustn't be written to. * are not generated by us and differ. And we
*/ * don't want to merge special locals that have a
if (prevLocal.getType().isOfType(local.getType()) * constant expression, e.g. this.
&& prevLocal.getName() != "this" */
&& (prevLocal.isNameGenerated() if (prevLocal.getType().isOfType(local.getType())
|| local.isNameGenerated() && (prevLocal.isNameGenerated()
|| localName.equals(prevLocal.getName()))) { || local.isNameGenerated()
local.combineWith(prevLocal); || localName.equals(prevLocal.getName()))
continue next_used; && prevLocal.getExpression() == null
&& local.getExpression() == null) {
local.combineWith(prevLocal);
continue next_used;
}
} }
} }
} }
LocalInfo previous = done.findLocal(localName); if (declarable.getName() != null) {
if (previous != null) { Enumeration doneEnum = done.elements();
/* A name conflict happened. */ while (doneEnum.hasMoreElements()) {
local.makeNameUnique(); Declarable previous = (Declarable) doneEnum.nextElement();
if (declarable.getName().equals(previous.getName())) {
/* A name conflict happened. */
declarable.makeNameUnique();
}
}
} }
done.addElement(local); done.add(declarable);
declare.addElement(local); declare.add(declarable);
} }
// System.err.println("makeDeclaration: declare = "+declare);
StructuredBlock[] subs = getSubBlocks(); StructuredBlock[] subs = getSubBlocks();
for (int i=0; i<subs.length; i++) for (int i=0; i<subs.length; i++)
subs[i].makeDeclaration(done); subs[i].makeDeclaration(done);
/* remove the variables again, since we leave the scope. /* remove the variables again, since we leave the scope.
*/ */
done.subtractExact(declare); done.removeAll(declare);
} }
public void checkConsistent() { public void checkConsistent() {
@ -569,7 +589,7 @@ public abstract class StructuredBlock {
* dumpInstruction afterwards. * dumpInstruction afterwards.
* @param writer The tabbed print writer, where we print to. * @param writer The tabbed print writer, where we print to.
*/ */
public void dumpSource(jode.decompiler.TabbedPrintWriter writer) public void dumpSource(TabbedPrintWriter writer)
throws java.io.IOException throws java.io.IOException
{ {
if ((GlobalOptions.debuggingFlags if ((GlobalOptions.debuggingFlags
@ -584,8 +604,9 @@ public abstract class StructuredBlock {
if (declare != null) { if (declare != null) {
java.util.Enumeration enum = declare.elements(); java.util.Enumeration enum = declare.elements();
while (enum.hasMoreElements()) { while (enum.hasMoreElements()) {
LocalInfo local = (LocalInfo) enum.nextElement(); Declarable decl = (Declarable) enum.nextElement();
dumpDeclaration(writer, local); decl.dumpDeclaration(writer);
writer.println(";");
} }
} }
dumpInstruction(writer); dumpInstruction(writer);
@ -594,20 +615,6 @@ public abstract class StructuredBlock {
jump.dumpSource(writer); jump.dumpSource(writer);
} }
/**
* Print the code for the declaration of a local variable.
* @param writer The tabbed print writer, where we print to.
* @param local The local that should be declared.
*/
public void dumpDeclaration(jode.decompiler.TabbedPrintWriter writer, LocalInfo local)
throws java.io.IOException
{
if (!local.isRemoved()) {
writer.printType(local.getType().getHint());
writer.println(" " + local.getName().toString() + ";");
}
}
/** /**
* Print the instruction expressing this structured block. * Print the instruction expressing this structured block.
* @param writer The tabbed print writer, where we print to. * @param writer The tabbed print writer, where we print to.

@ -21,6 +21,7 @@ package jode.flow;
import jode.decompiler.LocalInfo; import jode.decompiler.LocalInfo;
import jode.decompiler.TabbedPrintWriter; import jode.decompiler.TabbedPrintWriter;
import jode.expr.Expression; import jode.expr.Expression;
import jode.util.SimpleSet;
/** /**
* This class represents a synchronized structured block. * This class represents a synchronized structured block.
@ -70,12 +71,12 @@ public class SynchronizedBlock extends StructuredBlock {
return true; return true;
} }
public VariableSet getUsed() { public SimpleSet getDeclarables() {
VariableSet used = new VariableSet(); SimpleSet used = new SimpleSet();
if (object != null) if (object != null)
object.fillInGenSet(null, used); object.fillDeclarables(used);
else else
used.addElement(local); used.add(local);
return used; return used;
} }
@ -84,10 +85,12 @@ public class SynchronizedBlock extends StructuredBlock {
{ {
if (!isEntered) if (!isEntered)
writer.println("MISSING MONITORENTER"); writer.println("MISSING MONITORENTER");
writer.print("synchronized (" writer.print("synchronized (");
+ (object != null if (object != null)
? object.toString() object.dumpExpression(writer);
: local.getName()) + ")"); else
writer.print(local.getName());
writer.print(")");
writer.openBrace(); writer.openBrace();
writer.tab(); writer.tab();
bodyBlock.dumpSource(writer); bodyBlock.dumpSource(writer);

Loading…
Cancel
Save