Created
August 12, 2012 00:27
-
-
Save dain/3328120 to your computer and use it in GitHub Desktop.
Code that demonstrates problems with MLVM
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Build the code with ASM 4 and Guava 12 as follows: | |
$ javac -cp $HOME/.m2/repository/org/ow2/asm/asm-all/4.0/asm-all-4.0.jar:$HOME/.m2/repository/com/google/guava/guava/12.0/guava-12.0.jar:. FibGeneratedAsm.java | |
Code can be run with: | |
$ ~/jdk-back/1.8.0-mlvm-2012_08_01_10_07/Contents/Home/bin/java -cp $HOME/.m2/repository/org/o/asm/asm-all/4.0/asm-all-4.0.jar:$HOME/.m2/repository/com/google/guava/guava/12.0/guava-12.0.jar:. FibGeneratedAsm | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import com.google.common.base.Charsets; | |
import com.google.common.base.Preconditions; | |
import com.google.common.collect.Sets; | |
import com.google.common.primitives.Doubles; | |
import com.google.common.primitives.Longs; | |
import org.objectweb.asm.ClassReader; | |
import org.objectweb.asm.ClassWriter; | |
import org.objectweb.asm.Handle; | |
import org.objectweb.asm.tree.ClassNode; | |
import org.objectweb.asm.tree.InsnNode; | |
import org.objectweb.asm.tree.InvokeDynamicInsnNode; | |
import org.objectweb.asm.tree.JumpInsnNode; | |
import org.objectweb.asm.tree.LabelNode; | |
import org.objectweb.asm.tree.LdcInsnNode; | |
import org.objectweb.asm.tree.MethodInsnNode; | |
import org.objectweb.asm.tree.MethodNode; | |
import org.objectweb.asm.tree.VarInsnNode; | |
import org.objectweb.asm.util.CheckClassAdapter; | |
import org.objectweb.asm.util.TraceClassVisitor; | |
import java.io.PrintWriter; | |
import java.lang.invoke.CallSite; | |
import java.lang.invoke.ConstantCallSite; | |
import java.lang.invoke.MethodHandle; | |
import java.lang.invoke.MethodHandles; | |
import java.lang.invoke.MethodHandles.Lookup; | |
import java.lang.invoke.MethodType; | |
import java.nio.charset.Charset; | |
import java.util.ArrayList; | |
import java.util.Arrays; | |
import java.util.EnumSet; | |
import java.util.Set; | |
import static com.google.common.base.Preconditions.checkNotNull; | |
import static java.lang.String.format; | |
import static java.lang.invoke.MethodType.methodType; | |
import static org.objectweb.asm.Opcodes.ACC_PUBLIC; | |
import static org.objectweb.asm.Opcodes.ACC_STATIC; | |
import static org.objectweb.asm.Opcodes.ALOAD; | |
import static org.objectweb.asm.Opcodes.ARETURN; | |
import static org.objectweb.asm.Opcodes.ASTORE; | |
import static org.objectweb.asm.Opcodes.DUP; | |
import static org.objectweb.asm.Opcodes.H_INVOKESTATIC; | |
import static org.objectweb.asm.Opcodes.IFEQ; | |
import static org.objectweb.asm.Opcodes.INVOKESPECIAL; | |
import static org.objectweb.asm.Opcodes.INVOKESTATIC; | |
import static org.objectweb.asm.Opcodes.INVOKEVIRTUAL; | |
import static org.objectweb.asm.Opcodes.RETURN; | |
import static org.objectweb.asm.Opcodes.V1_7; | |
public class FibGeneratedAsm | |
{ | |
private static final boolean VERIFY_BYTE_CODE = false; | |
private static final boolean DUMP_BYTE_CODE = false; | |
private static final DynamicClassLoader classLoader = new DynamicClassLoader(); | |
private static MethodHandle fibMethodHandle; | |
public static final Handle BOOTSTRAP_METHOD = new Handle( | |
H_INVOKESTATIC, | |
"FibGeneratedAsm", | |
"bootstrap", | |
methodType(CallSite.class, Lookup.class, String.class, MethodType.class, String.class).toMethodDescriptorString()); | |
private static enum Features { | |
MH_CAST, | |
PHP_REFERENCE, | |
VAR_CLEANUP, | |
TEMP_REFERENCES, | |
} | |
private static Set<Features> enabled; | |
public static void main(String[] args) | |
throws Exception | |
{ | |
enabled = EnumSet.allOf(Features.class); | |
run(); | |
for (Set<Features> features : Sets.powerSet(EnumSet.allOf(Features.class))) { | |
enabled = features; | |
run(); | |
} | |
} | |
private static void run() | |
throws Exception | |
{ | |
// generate a new script class | |
Script script = generateFibScriptAsm(); | |
fibMethodHandle = MethodHandles.lookup().findStatic(script.getClass(), "fib", methodType(Object.class, Context.class, Object.class)); | |
System.err.println(); | |
for (int i = 0; i < 3; i++) { | |
long start = System.nanoTime(); | |
script.execute(null); | |
long time = (System.nanoTime() - start); | |
System.err.println(String.format("Time: %3.2fs %s", time / 1.0e9, enabled)); | |
} | |
} | |
public static Script generateFibScriptAsm() | |
throws Exception | |
{ | |
ClassNode classNode = new ClassNode(); | |
classNode.version = V1_7; | |
classNode.access = ACC_PUBLIC; | |
classNode.name = "Fib_asm_" + System.currentTimeMillis(); | |
classNode.superName = "java/lang/Object"; | |
classNode.interfaces.add(Script.class.getName().replace('.', '/')); | |
MethodNode constructor = new MethodNode(); | |
constructor.access = ACC_PUBLIC; | |
constructor.name = "<init>"; | |
constructor.desc = "()V"; | |
constructor.exceptions = new ArrayList<>(); | |
constructor.instructions.add(new VarInsnNode(ALOAD, 0)); | |
constructor.instructions.add(new MethodInsnNode(INVOKESPECIAL, "java/lang/Object", "<init>", "()V")); | |
constructor.instructions.add(new InsnNode(RETURN)); | |
classNode.methods.add(constructor); | |
MethodNode executeMethod = new MethodNode(); | |
executeMethod.access = ACC_PUBLIC; | |
executeMethod.name = "execute"; | |
executeMethod.desc = "(LFibGeneratedAsm$Context;)Ljava/lang/Object;"; | |
executeMethod.exceptions = new ArrayList<>(); | |
executeMethod.instructions.add(new VarInsnNode(ALOAD, 1)); | |
executeMethod.instructions.add(new LdcInsnNode(37L)); | |
executeMethod.instructions.add(new MethodInsnNode(INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;")); | |
executeMethod.instructions.add(new MethodInsnNode(INVOKESTATIC, classNode.name, "fib", "(LFibGeneratedAsm$Context;Ljava/lang/Object;)Ljava/lang/Object;")); | |
executeMethod.instructions.add(new InsnNode(ARETURN)); | |
classNode.methods.add(executeMethod); | |
MethodNode fibMethod = new MethodNode(); | |
fibMethod.access = ACC_PUBLIC + ACC_STATIC; | |
fibMethod.name = "fib"; | |
fibMethod.desc = "(LFibGeneratedAsm$Context;Ljava/lang/Object;)Ljava/lang/Object;"; | |
fibMethod.exceptions = new ArrayList<>(); | |
// box n in a PhpReference | |
fibMethod.instructions.add(new VarInsnNode(ALOAD, 1)); | |
fibMethod.instructions.add(new MethodInsnNode(INVOKESTATIC, "FibGeneratedAsm$PhpReference", "createPhpReference", "(Ljava/lang/Object;)LFibGeneratedAsm$PhpReference;")); | |
fibMethod.instructions.add(new VarInsnNode(ASTORE, 1)); | |
// if (n < 2) goto recurse | |
fibMethod.instructions.add(new VarInsnNode(ALOAD, 1)); | |
fibMethod.instructions.add(new MethodInsnNode(INVOKEVIRTUAL, "FibGeneratedAsm$PhpReference", "get", "()Ljava/lang/Object;")); | |
fibMethod.instructions.add(new LdcInsnNode(2L)); | |
fibMethod.instructions.add(new MethodInsnNode(INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;")); | |
fibMethod.instructions.add(new MethodInsnNode(INVOKESTATIC, "FibGeneratedAsm", "lessThan", "(Ljava/lang/Object;Ljava/lang/Object;)Z")); | |
LabelNode recurse = new LabelNode(); | |
fibMethod.instructions.add(new JumpInsnNode(IFEQ, recurse)); | |
// return n | |
fibMethod.instructions.add(new VarInsnNode(ALOAD, 1)); | |
fibMethod.instructions.add(new MethodInsnNode(INVOKEVIRTUAL, "FibGeneratedAsm$PhpReference", "get", "()Ljava/lang/Object;")); | |
if (enabled.contains(Features.VAR_CLEANUP)) | |
{ | |
// increment reference count of n | |
fibMethod.instructions.add(new InsnNode(DUP)); | |
fibMethod.instructions.add(new MethodInsnNode(INVOKESTATIC, "FibGeneratedAsm$ReferenceCounted", "incrementReferenceCount", "(Ljava/lang/Object;)V")); | |
// decrement count of context | |
fibMethod.instructions.add(new VarInsnNode(ALOAD, 0)); | |
fibMethod.instructions.add(new MethodInsnNode(INVOKESTATIC, "FibGeneratedAsm$ReferenceCounted", "decrementReferenceCount", "(Ljava/lang/Object;)V")); | |
// decrement count of reference to n | |
fibMethod.instructions.add(new VarInsnNode(ALOAD, 1)); | |
fibMethod.instructions.add(new MethodInsnNode(INVOKEVIRTUAL, "FibGeneratedAsm$ReferenceCounted", "$decrementReferenceCount", "()V")); | |
} | |
fibMethod.instructions.add(new InsnNode(ARETURN)); | |
// if (n >= 2) | |
fibMethod.instructions.add(recurse); | |
// fib(c, n - 1) | |
fibMethod.instructions.add(new VarInsnNode(ALOAD, 0)); | |
fibMethod.instructions.add(new VarInsnNode(ALOAD, 1)); | |
fibMethod.instructions.add(new MethodInsnNode(INVOKEVIRTUAL, "FibGeneratedAsm$PhpReference", "get", "()Ljava/lang/Object;")); | |
fibMethod.instructions.add(new LdcInsnNode(1L)); | |
fibMethod.instructions.add(new MethodInsnNode(INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;")); | |
fibMethod.instructions.add(new MethodInsnNode(INVOKESTATIC, "FibGeneratedAsm", "sub", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Number;")); | |
fibMethod.instructions.add(new InvokeDynamicInsnNode("dyn:call:fib:", | |
MethodType.methodType(Object.class, Object.class, Object.class).toMethodDescriptorString(), | |
BOOTSTRAP_METHOD, | |
"(LFibGeneratedAsm$Context;Ljava/lang/Object;)Ljava/lang/Object;")); | |
if (enabled.contains(Features.TEMP_REFERENCES)) | |
{ | |
fibMethod.instructions.add(new InsnNode(DUP)); | |
fibMethod.instructions.add(new VarInsnNode(ASTORE, 2)); | |
} | |
// fib(c, n - 2) | |
fibMethod.instructions.add(new VarInsnNode(ALOAD, 0)); | |
fibMethod.instructions.add(new VarInsnNode(ALOAD, 1)); | |
fibMethod.instructions.add(new MethodInsnNode(INVOKEVIRTUAL, "FibGeneratedAsm$PhpReference", "get", "()Ljava/lang/Object;")); | |
fibMethod.instructions.add(new LdcInsnNode(2L)); | |
fibMethod.instructions.add(new MethodInsnNode(INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;")); | |
fibMethod.instructions.add(new MethodInsnNode(INVOKESTATIC, "FibGeneratedAsm", "sub", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Number;")); | |
fibMethod.instructions.add(new InvokeDynamicInsnNode("dyn:call:fib:", | |
MethodType.methodType(Object.class, Object.class, Object.class).toMethodDescriptorString(), | |
BOOTSTRAP_METHOD, | |
"(LFibGeneratedAsm$Context;Ljava/lang/Object;)Ljava/lang/Object;")); | |
if (enabled.contains(Features.TEMP_REFERENCES)) | |
{ | |
fibMethod.instructions.add(new InsnNode(DUP)); | |
fibMethod.instructions.add(new VarInsnNode(ASTORE, 3)); | |
} | |
fibMethod.instructions.add(new MethodInsnNode(INVOKESTATIC, "FibGeneratedAsm", "add", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Number;")); | |
if (enabled.contains(Features.TEMP_REFERENCES)) | |
{ | |
fibMethod.instructions.add(new VarInsnNode(ALOAD, 2)); | |
fibMethod.instructions.add(new MethodInsnNode(INVOKESTATIC, "FibGeneratedAsm$ReferenceCounted", "decrementReferenceCount", "(Ljava/lang/Object;)V")); | |
fibMethod.instructions.add(new VarInsnNode(ALOAD, 3)); | |
fibMethod.instructions.add(new MethodInsnNode(INVOKESTATIC, "FibGeneratedAsm$ReferenceCounted", "decrementReferenceCount", "(Ljava/lang/Object;)V")); | |
} | |
if (enabled.contains(Features.VAR_CLEANUP)) | |
{ | |
// increment reference count of n | |
fibMethod.instructions.add(new InsnNode(DUP)); | |
fibMethod.instructions.add(new MethodInsnNode(INVOKESTATIC, "FibGeneratedAsm$ReferenceCounted", "incrementReferenceCount", "(Ljava/lang/Object;)V")); | |
// decrement count of context | |
fibMethod.instructions.add(new VarInsnNode(ALOAD, 0)); | |
fibMethod.instructions.add(new MethodInsnNode(INVOKESTATIC, "FibGeneratedAsm$ReferenceCounted", "decrementReferenceCount", "(Ljava/lang/Object;)V")); | |
// decrement count of reference to n | |
fibMethod.instructions.add(new VarInsnNode(ALOAD, 1)); | |
fibMethod.instructions.add(new MethodInsnNode(INVOKEVIRTUAL, "FibGeneratedAsm$ReferenceCounted", "$decrementReferenceCount", "()V")); | |
} | |
fibMethod.instructions.add(new InsnNode(ARETURN)); | |
classNode.methods.add(fibMethod); | |
Script myScript = loadScript(classNode); | |
return myScript; | |
} | |
// | |
// Bootstrap (Linker) | |
// | |
public static CallSite bootstrap(Lookup caller, String name, MethodType type, String signature) | |
{ | |
MethodHandle linkedFib = fibMethodHandle; | |
// adapt to call site | |
if (enabled.contains(Features.MH_CAST)) { | |
linkedFib = MethodHandles.explicitCastArguments(linkedFib, methodType(Object.class, Object.class, Object.class)); | |
linkedFib = MethodHandles.filterArguments(linkedFib, 0, MethodHandles.identity(Object.class)); | |
linkedFib = MethodHandles.explicitCastArguments(linkedFib, methodType(Object.class, Context.class, Object.class)); | |
linkedFib = MethodHandles.explicitCastArguments(linkedFib, methodType(Object.class, Object.class, Object.class)); | |
} | |
else { | |
linkedFib = MethodHandles.explicitCastArguments(linkedFib, methodType(Object.class, Object.class, Object.class)); | |
linkedFib = MethodHandles.explicitCastArguments(linkedFib, methodType(Object.class, Object.class, Object.class)); | |
} | |
return new ConstantCallSite(linkedFib); | |
} | |
// | |
// System Interfaces | |
// | |
public interface Script | |
{ | |
Object execute(Context context) | |
throws Exception; | |
} | |
public static class Context { | |
} | |
public static abstract class ReferenceCounted | |
{ | |
private int referenceCount = 1; | |
public final void $incrementReferenceCount() | |
{ | |
referenceCount++; | |
} | |
public final void $decrementReferenceCount() | |
{ | |
Preconditions.checkState(referenceCount != 0, "Count is zero"); | |
referenceCount--; | |
if (referenceCount == 0) { | |
$destroy(); | |
} | |
} | |
protected abstract void $destroy(); | |
public static void incrementReferenceCount(Object value) | |
{ | |
if (value instanceof ReferenceCounted) { | |
((ReferenceCounted) value).$incrementReferenceCount(); | |
} | |
} | |
public static void decrementReferenceCount(Object value) | |
{ | |
if (value instanceof ReferenceCounted) { | |
((ReferenceCounted) value).$decrementReferenceCount(); | |
} | |
} | |
} | |
public static class PhpReference extends ReferenceCounted | |
{ | |
public static PhpReference createPhpReference(Object value) | |
{ | |
return new PhpReference(value); | |
} | |
private Object value; | |
public PhpReference(Object value) | |
{ | |
Preconditions.checkArgument(value == null || value.getClass() != PhpReference.class, "value is a PhpReference"); | |
incrementReferenceCount(value); | |
this.value = value; | |
} | |
public Object get() | |
{ | |
return value; | |
} | |
public void unset() | |
{ | |
decrementReferenceCount(value); | |
value = null; | |
} | |
@Override | |
protected void $destroy() | |
{ | |
unset(); | |
} | |
} | |
public static class PhpString | |
{ | |
private final String string; | |
private final byte[] bytes; | |
private PhpString(String string, Charset charset) | |
{ | |
this.string = checkNotNull(string, "string"); | |
this.bytes = string.getBytes(checkNotNull(charset, "charset")); | |
} | |
public boolean isEmpty() | |
{ | |
return bytes.length == 0; | |
} | |
public int length() | |
{ | |
return bytes.length; | |
} | |
@Override | |
public String toString() | |
{ | |
return string; | |
} | |
@Override | |
public boolean equals(Object o) | |
{ | |
if (this == o) { | |
return true; | |
} | |
if ((o == null) || (getClass() != o.getClass())) { | |
return false; | |
} | |
PhpString phpString = (PhpString) o; | |
return Arrays.equals(bytes, phpString.bytes); | |
} | |
@Override | |
public int hashCode() | |
{ | |
return Arrays.hashCode(bytes); | |
} | |
} | |
// | |
// Class Loading | |
// | |
private static Script loadScript(ClassNode classNode) | |
throws InstantiationException, IllegalAccessException | |
{ | |
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES); | |
classNode.accept(cw); | |
byte[] byteCode = cw.toByteArray(); | |
if (VERIFY_BYTE_CODE) { | |
ClassReader reader = new ClassReader(byteCode); | |
CheckClassAdapter.verify(reader, true, new PrintWriter(System.out)); | |
} | |
if (DUMP_BYTE_CODE) { | |
ClassReader classReader = new ClassReader(byteCode); | |
classReader.accept(new TraceClassVisitor(new PrintWriter(System.err)), ClassReader.SKIP_FRAMES); | |
} | |
Class<?> myClass = classLoader.defineClass(classNode.name, byteCode); | |
return (Script) myClass.newInstance(); | |
} | |
public static class DynamicClassLoader extends ClassLoader | |
{ | |
public DynamicClassLoader() | |
{ | |
super(DynamicClassLoader.class.getClassLoader()); | |
} | |
public Class<?> defineClass(String className, byte[] byteCode) | |
{ | |
return super.defineClass(className, byteCode, 0, byteCode.length); | |
} | |
} | |
// | |
// Basic Operators | |
// | |
public static Number sub(Object left, Object right) | |
{ | |
// use extra level of indirection to simulate real code | |
return sub2(left, right); | |
} | |
public static Number sub2(Object l, Object r) | |
{ | |
Number left = toNumber(l); | |
Number right = toNumber(r); | |
if (left instanceof Double || right instanceof Double) { | |
return left.doubleValue() - right.doubleValue(); | |
} | |
return left.longValue() - right.longValue(); | |
} | |
public static Number add(Object left, Object right) | |
{ | |
// use extra level of indirection to simulate real code | |
return add2(left, right); | |
} | |
public static Number add2(Object l, Object r) | |
{ | |
Number left = toNumber(l); | |
Number right = toNumber(r); | |
if (left instanceof Double || right instanceof Double) { | |
return left.doubleValue() + right.doubleValue(); | |
} | |
return left.longValue() + right.longValue(); | |
} | |
public static boolean lessThan(Object left, Object right) | |
{ | |
return toPrimitiveBoolean(lessThanBoxed(left, right)); | |
} | |
public static Boolean lessThanBoxed(Object left, Object right) | |
{ | |
return compare(left, right) < 0; | |
} | |
public static int compare(Object left, Object right) | |
{ | |
if (left == null && right == null) { | |
return 0; | |
} | |
if (left instanceof String && right instanceof String) { | |
// TODO if left and right are numeric strings, coerce | |
return ((String) left).compareTo((String) right); | |
} | |
if (left instanceof Long && right instanceof Long) { | |
return Longs.compare((Long) left, (Long) right); | |
} | |
if (left instanceof Number && right instanceof Number) { | |
// long-double, double-long or double-double | |
return Doubles.compare(((Number) left).doubleValue(), ((Number) right).doubleValue()); | |
} | |
if (left instanceof Boolean && right instanceof Boolean) { | |
Boolean leftBoolean = (Boolean) left; | |
Boolean rightBoolean = (Boolean) right; | |
int leftInt = leftBoolean ? 1 : 0; | |
int rightInt = rightBoolean ? 1 : 0; | |
return leftInt - rightInt; | |
} | |
if (right == null) { | |
if (left instanceof String) { | |
return ((String) left).compareTo(""); | |
} | |
else { | |
return toBoolean(left) ? 1 : 0; | |
} | |
} | |
else if (left == null) { | |
if (right instanceof String) { | |
return "".compareTo((String) right); | |
} | |
else { | |
return toBoolean(right) ? -1 : 0; | |
} | |
} | |
if (left instanceof Number || right instanceof Number) { | |
Number leftNumber = toNumber(left); | |
Number rightNumber = toNumber(right); | |
return compare(leftNumber, rightNumber); | |
} | |
throw new UnsupportedOperationException(format("Can't compare %s (%s) and %s (%s)", left, left.getClass().getName(), right, right.getClass().getName())); | |
} | |
public static int compare(Number left, Number right) | |
{ | |
if (left instanceof Double || right instanceof Double) { | |
return Doubles.compare(left.doubleValue(), right.doubleValue()); | |
} | |
return Longs.compare(left.longValue(), right.longValue()); | |
} | |
// | |
// Type Coercion | |
// | |
public static boolean toPrimitiveBoolean(Object obj) | |
{ | |
return toBoolean(obj); | |
} | |
public static Boolean toBoolean(Object obj) | |
{ | |
if (obj instanceof Boolean) { | |
return (Boolean) obj; | |
} | |
if (obj instanceof Double) { | |
return ((Double) obj) != 0.0; | |
} | |
if (obj instanceof Long) { | |
return ((Long) obj) != 0L; | |
} | |
if (obj instanceof String) { | |
String s = (String) obj; | |
return !(s.isEmpty() || s.equals("0")); | |
} | |
if (obj instanceof PhpString) { | |
PhpString s = (PhpString) obj; | |
return !(s.isEmpty() || s.equals(new PhpString("0", Charsets.UTF_8))); | |
} | |
return (obj != null); | |
} | |
public static Number toNumber(Object obj) | |
{ | |
if (obj instanceof Long || obj instanceof Double) { | |
return (Number) obj; | |
} | |
if (obj instanceof Float) { | |
return ((Float) obj).doubleValue(); | |
} | |
if (obj instanceof Number) { | |
return ((Number) obj).longValue(); | |
} | |
if (obj instanceof Boolean) { | |
return ((Boolean) obj) ? 1L : 0L; | |
} | |
if ((obj instanceof String) || (obj instanceof PhpString)) { | |
if (obj instanceof PhpString) { | |
obj = obj.toString(); | |
} | |
try { | |
return Long.parseLong((String) obj); | |
} | |
catch (NumberFormatException e) { | |
// ignore | |
} | |
try { | |
return Double.parseDouble((String) obj); | |
} | |
catch (NumberFormatException e) { | |
// ignore | |
} | |
return (long) 0; | |
} | |
if (obj == null) { | |
return (long) 0; | |
} | |
return (long) 1; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$ java -version | |
openjdk version "1.8.0-b49" | |
OpenJDK Runtime Environment (build 1.8.0-b49-20120728) | |
OpenJDK 64-Bit Server VM (build 24.0-b16, mixed mode) | |
$java -cp $HOME/.m2/repository/org/ow2/asm/asm-all/4.0/asm-all-4.0.jar:$HOME/.m2/repository/com/google/guava/guava/12.0/guava-12.0.jar:. FibGeneratedAsm | |
Time: 0.59s [MH_CAST, PHP_REFERENCE, VAR_CLEANUP, TEMP_REFERENCES] | |
Time: 0.54s [MH_CAST, PHP_REFERENCE, VAR_CLEANUP, TEMP_REFERENCES] | |
Time: 0.53s [MH_CAST, PHP_REFERENCE, VAR_CLEANUP, TEMP_REFERENCES] | |
Time: 0.50s [] | |
Time: 0.49s [] | |
Time: 0.49s [] | |
Time: 0.50s [MH_CAST] | |
Time: 0.49s [MH_CAST] | |
Time: 0.49s [MH_CAST] | |
Time: 0.50s [PHP_REFERENCE] | |
Time: 0.49s [PHP_REFERENCE] | |
Time: 0.48s [PHP_REFERENCE] | |
Time: 0.50s [MH_CAST, PHP_REFERENCE] | |
Time: 0.49s [MH_CAST, PHP_REFERENCE] | |
Time: 0.49s [MH_CAST, PHP_REFERENCE] | |
Time: 0.52s [VAR_CLEANUP] | |
Time: 0.50s [VAR_CLEANUP] | |
Time: 0.50s [VAR_CLEANUP] | |
Time: 0.52s [MH_CAST, VAR_CLEANUP] | |
Time: 0.50s [MH_CAST, VAR_CLEANUP] | |
Time: 0.50s [MH_CAST, VAR_CLEANUP] | |
Time: 0.53s [PHP_REFERENCE, VAR_CLEANUP] | |
Time: 0.50s [PHP_REFERENCE, VAR_CLEANUP] | |
Time: 0.50s [PHP_REFERENCE, VAR_CLEANUP] | |
Time: 0.52s [MH_CAST, PHP_REFERENCE, VAR_CLEANUP] | |
Time: 0.51s [MH_CAST, PHP_REFERENCE, VAR_CLEANUP] | |
Time: 0.50s [MH_CAST, PHP_REFERENCE, VAR_CLEANUP] | |
Time: 0.53s [TEMP_REFERENCES] | |
Time: 0.52s [TEMP_REFERENCES] | |
Time: 0.51s [TEMP_REFERENCES] | |
Time: 0.53s [MH_CAST, TEMP_REFERENCES] | |
Time: 0.51s [MH_CAST, TEMP_REFERENCES] | |
Time: 0.52s [MH_CAST, TEMP_REFERENCES] | |
Time: 0.53s [PHP_REFERENCE, TEMP_REFERENCES] | |
Time: 0.51s [PHP_REFERENCE, TEMP_REFERENCES] | |
Time: 0.51s [PHP_REFERENCE, TEMP_REFERENCES] | |
Time: 0.53s [MH_CAST, PHP_REFERENCE, TEMP_REFERENCES] | |
Time: 0.51s [MH_CAST, PHP_REFERENCE, TEMP_REFERENCES] | |
Time: 0.51s [MH_CAST, PHP_REFERENCE, TEMP_REFERENCES] | |
Time: 0.55s [VAR_CLEANUP, TEMP_REFERENCES] | |
Time: 0.53s [VAR_CLEANUP, TEMP_REFERENCES] | |
Time: 0.53s [VAR_CLEANUP, TEMP_REFERENCES] | |
Time: 0.55s [MH_CAST, VAR_CLEANUP, TEMP_REFERENCES] | |
Time: 0.53s [MH_CAST, VAR_CLEANUP, TEMP_REFERENCES] | |
Time: 0.53s [MH_CAST, VAR_CLEANUP, TEMP_REFERENCES] | |
Time: 0.55s [PHP_REFERENCE, VAR_CLEANUP, TEMP_REFERENCES] | |
Time: 0.53s [PHP_REFERENCE, VAR_CLEANUP, TEMP_REFERENCES] | |
Time: 0.53s [PHP_REFERENCE, VAR_CLEANUP, TEMP_REFERENCES] | |
Time: 0.55s [MH_CAST, PHP_REFERENCE, VAR_CLEANUP, TEMP_REFERENCES] | |
Time: 0.53s [MH_CAST, PHP_REFERENCE, VAR_CLEANUP, TEMP_REFERENCES] | |
Time: 0.53s [MH_CAST, PHP_REFERENCE, VAR_CLEANUP, TEMP_REFERENCES] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$ ~/jdk-back/1.8.0-mlvm-2012_08_01_10_07/Contents/Home/bin/java -version | |
openjdk version "1.8.0-internal" | |
OpenJDK Runtime Environment (build 1.8.0-internal-dain_2012_08_01_10_07-b00) | |
OpenJDK 64-Bit Server VM (build 24.0-b17, mixed mode) | |
$ ~/jdk-back/1.8.0-mlvm-2012_08_01_10_07/Contents/Home/bin/java -cp $HOME/.m2/repository/org/o/asm/asm-all/4.0/asm-all-4.0.jar:$HOME/.m2/repository/com/google/guava/guava/12.0/guava-12.0.jar:. FibGeneratedAsm | |
Time: 1.05s [MH_CAST, PHP_REFERENCE, VAR_CLEANUP, TEMP_REFERENCES] | |
Time: 0.90s [MH_CAST, PHP_REFERENCE, VAR_CLEANUP, TEMP_REFERENCES] | |
Time: 0.86s [MH_CAST, PHP_REFERENCE, VAR_CLEANUP, TEMP_REFERENCES] | |
Time: 0.53s [] | |
Time: 0.51s [] | |
Time: 0.51s [] | |
Time: 0.53s [MH_CAST] | |
Time: 0.51s [MH_CAST] | |
Time: 0.51s [MH_CAST] | |
Time: 0.53s [PHP_REFERENCE] | |
Time: 0.51s [PHP_REFERENCE] | |
Time: 0.51s [PHP_REFERENCE] | |
Time: 0.53s [MH_CAST, PHP_REFERENCE] | |
Time: 0.51s [MH_CAST, PHP_REFERENCE] | |
Time: 0.51s [MH_CAST, PHP_REFERENCE] | |
Time: 0.54s [VAR_CLEANUP] | |
Time: 0.52s [VAR_CLEANUP] | |
Time: 0.52s [VAR_CLEANUP] | |
Time: 0.83s [MH_CAST, VAR_CLEANUP] | |
Time: 0.83s [MH_CAST, VAR_CLEANUP] | |
Time: 0.80s [MH_CAST, VAR_CLEANUP] | |
Time: 0.54s [PHP_REFERENCE, VAR_CLEANUP] | |
Time: 0.52s [PHP_REFERENCE, VAR_CLEANUP] | |
Time: 0.52s [PHP_REFERENCE, VAR_CLEANUP] | |
Time: 0.83s [MH_CAST, PHP_REFERENCE, VAR_CLEANUP] | |
Time: 0.79s [MH_CAST, PHP_REFERENCE, VAR_CLEANUP] | |
Time: 0.79s [MH_CAST, PHP_REFERENCE, VAR_CLEANUP] | |
Time: 0.54s [TEMP_REFERENCES] | |
Time: 0.51s [TEMP_REFERENCES] | |
Time: 0.52s [TEMP_REFERENCES] | |
Time: 0.54s [MH_CAST, TEMP_REFERENCES] | |
Time: 0.52s [MH_CAST, TEMP_REFERENCES] | |
Time: 0.52s [MH_CAST, TEMP_REFERENCES] | |
Time: 0.54s [PHP_REFERENCE, TEMP_REFERENCES] | |
Time: 0.51s [PHP_REFERENCE, TEMP_REFERENCES] | |
Time: 0.52s [PHP_REFERENCE, TEMP_REFERENCES] | |
Time: 0.54s [MH_CAST, PHP_REFERENCE, TEMP_REFERENCES] | |
Time: 0.52s [MH_CAST, PHP_REFERENCE, TEMP_REFERENCES] | |
Time: 0.52s [MH_CAST, PHP_REFERENCE, TEMP_REFERENCES] | |
Time: 0.58s [VAR_CLEANUP, TEMP_REFERENCES] | |
Time: 0.53s [VAR_CLEANUP, TEMP_REFERENCES] | |
Time: 0.53s [VAR_CLEANUP, TEMP_REFERENCES] | |
Time: 0.91s [MH_CAST, VAR_CLEANUP, TEMP_REFERENCES] | |
Time: 0.88s [MH_CAST, VAR_CLEANUP, TEMP_REFERENCES] | |
Time: 0.88s [MH_CAST, VAR_CLEANUP, TEMP_REFERENCES] | |
Time: 0.57s [PHP_REFERENCE, VAR_CLEANUP, TEMP_REFERENCES] | |
Time: 0.54s [PHP_REFERENCE, VAR_CLEANUP, TEMP_REFERENCES] | |
Time: 0.53s [PHP_REFERENCE, VAR_CLEANUP, TEMP_REFERENCES] | |
Time: 0.91s [MH_CAST, PHP_REFERENCE, VAR_CLEANUP, TEMP_REFERENCES] | |
Time: 0.88s [MH_CAST, PHP_REFERENCE, VAR_CLEANUP, TEMP_REFERENCES] | |
Time: 0.88s [MH_CAST, PHP_REFERENCE, VAR_CLEANUP, TEMP_REFERENCES] | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment