Skip to content

Commit

Permalink
Fixed: Aconst_null types in stack and locals. A more elegant solution.
Browse files Browse the repository at this point in the history
  • Loading branch information
Sperry, Daniel committed Feb 12, 2016
1 parent fdc8098 commit 538968c
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 76 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@
import org.objectweb.asm.tree.analysis.BasicValue;
import org.objectweb.asm.tree.analysis.Frame;
import org.objectweb.asm.tree.analysis.Interpreter;
import org.objectweb.asm.tree.analysis.Value;

import java.util.Arrays;

Expand All @@ -64,7 +63,6 @@ static class ExtendedValue extends BasicValue
AbstractInsnNode insnNode;
boolean uninitialized;
public BasicValue[] undecided;
private BasicValue replacement;

public ExtendedValue(final Type type)
{
Expand Down Expand Up @@ -93,17 +91,6 @@ public String toString()
{
return undecided != null ? "?" : uninitialized ? "%" + super.toString() : super.toString();
}


public void setReplacement(final BasicValue replacement)
{
this.replacement = replacement;
}

public BasicValue getReplacement()
{
return replacement;
}
}

static class ExtendedFrame extends Frame<BasicValue>
Expand Down Expand Up @@ -215,45 +202,15 @@ public boolean merge(final Frame<? extends BasicValue> frame,
if (force)
{
// uses the current frame
computeReplacements(frame);
return true;
}
if (frame instanceof ExtendedFrame && ((ExtendedFrame) frame).force)
{
((ExtendedFrame) frame).computeReplacements(this);
init(frame);
return true;
}
return super.merge(frame, interpreter);
}

private void computeReplacements(final Frame other)
{
for (int i = 0; i < other.getLocals(); ++i)
{
final Value v1 = other.getLocal(i);
final BasicValue v2 = getLocal(i);
computeReplacement(v1, v2);
}
for (int i = 0; i < other.getStackSize(); ++i)
{
final Value v1 = other.getStack(i);
final BasicValue v2 = getStack(i);
computeReplacement(v1, v2);
}
}

private void computeReplacement(final Value v1, final BasicValue v2)
{
if (v1 instanceof ExtendedValue)
{
final Type type = ((ExtendedValue) v1).getType();
if (type != null && "Lnull;".equals(type.toString()))
{
((ExtendedValue) v1).setReplacement(v2);
}
}
}
}

/**
Expand Down Expand Up @@ -420,36 +377,4 @@ else if (v instanceof LabelNode)
}
return interpreter.newValue(null);
}

@Override
public Frame[] analyze(final String owner, final MethodNode m) throws AnalyzerException
{
final Frame[] frames = super.analyze(owner, m);

// perform replacements
for (Frame frame : frames)
{
if (frame != null)
{
for (int i = 0; i < frame.getLocals(); ++i)
{
final Value v1 = frame.getLocal(i);
if (v1 instanceof ExtendedValue && ((ExtendedValue) v1).getReplacement() != null)
{
frame.setLocal(i, ((ExtendedValue) v1).getReplacement());
}

}
for (int i = 0; i < frame.getStackSize(); ++i)
{
final Value v1 = frame.getStack(i);
if (v1 instanceof ExtendedValue && ((ExtendedValue) v1).getReplacement() != null)
{
// TODO: handle in the frame opcode creation
}
}
}
}
return frames;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ public class Transformer implements ClassFileTransformer
private static final String COMPLETION_STAGE_RET = ")Ljava/util/concurrent/CompletionStage;";

private static final String _THIS = "_this";
private static final Type ACONST_NULL_TYPE = Type.getObjectType("null");

public static final String JOIN_METHOD_NAME = "join";
public static final String JOIN_METHOD_DESC = "()Ljava/lang/Object;";
Expand Down Expand Up @@ -740,6 +741,10 @@ public void visitInsn(final int opcode)

private Argument mapLocalToLambdaArgument(final MethodNode originalMethod, SwitchEntry se, final List<Argument> arguments, final int local, final BasicValue value)
{
if (ACONST_NULL_TYPE.equals(value.getType()))
{
return null;
}
Argument argument = null;
String name = local < originalMethod.maxLocals ? guessName(originalMethod, se, local) : "_stack$" + (local - originalMethod.maxLocals);

Expand Down Expand Up @@ -1383,7 +1388,12 @@ private Object toFrameType(final BasicValue value)
case Type.DOUBLE:
return Opcodes.DOUBLE;
}
return type.getInternalName();
final String internalName = type.getInternalName();
if (ACONST_NULL_TYPE.equals(type))
{
return Opcodes.NULL;
}
return internalName;
}

private boolean isAwaitCall(final MethodInsnNode methodIns)
Expand Down
88 changes: 88 additions & 0 deletions async/src/test/java/com/ea/async/test/AConstNullTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -91,4 +91,92 @@ public static Task<Void> doIt(Task<Void> task)
}
}

@Test
public void nullInitialization3() throws Exception
{
final Task<Void> res = NullInit3.doIt(getBlockedTask());
completeFutures();
assertNull(res.join());

}

public static class NullInit3
{
public static Task<Void> doIt(Task<Void> task)
{
String x = null;
call0(x, await(task));
return Task.done();
}
}

public static void call0(final Object a, final Object b)
{
}


@Test
public void nullInitialization4() throws Exception
{
final Task<Void> res = NullInit4.doIt(getBlockedTask());
completeFutures();
assertNull(res.join());

}

public static class NullInit4
{
public static Task<Void> doIt(Task<String> task)
{
String x = null;
call0(await(task), x);
return Task.done();
}
}


@Test
public void nullInTheStack() throws Exception
{
debugTransform(AConstNullTest.class.getName() + "$NullInTheStack");
final Task<Void> res = NullInTheStack.doIt(getBlockedTask());
completeFutures();
assertNull(res.join());
}

public static class NullInTheStack
{
public static Task<Void> doIt(Task<Void> task)
{
call2(null, await(task));
return Task.done();
}

private static void call2(final Object o, final Object p)
{
}
}


@Test
public void nullInTheStack2() throws Exception
{
debugTransform(AConstNullTest.class.getName() + "$NullInTheStack2");
final Task<Void> res = NullInTheStack2.doIt(getBlockedTask());
completeFutures();
assertNull(res.join());
}

public static class NullInTheStack2
{
public static Task<Void> doIt(Task<Void> task)
{
call2(null, await(task));
return Task.done();
}
private static void call2(final String o, final Object p)
{
}

}
}

0 comments on commit 538968c

Please sign in to comment.