--- /dev/null 2016-04-25 11:46:41.725730096 -0400 +++ new/test/runtime/locallong/LocalLongHelper.java 2016-09-06 17:16:27.862080535 -0400 @@ -0,0 +1,84 @@ +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; +import java.lang.StackWalker.StackFrame; + +public class LocalLongHelper { + static StackWalker sw; + static Method intValue; + static Method getLocals; + static Class primitiveValueClass; + static Method primitiveType; + static Method getMethodType; + static Field memberName; + static Field offset; + + public static void main(String[] args) throws Throwable { + setupReflectionStatics(); + new LocalLongHelper().longArg(0xC0FFEE, 0x1234567890ABCDEFL); + } + + /* + * The first 4 local slots should be: + * 0: this + * 1: int "i" + * 2: long "l", first slot + * 3: long "l", second slot + */ + public long longArg(int i, long l) throws Throwable { + List frames = sw.walk(s -> s.collect(Collectors.toList())); + Object[] locals = (Object[]) getLocals.invoke(frames.get(0)); + + int locals_1 = (int) intValue.invoke(locals[1]); // java.lang.LiveStackFrame$PrimitiveValue.intValue() + int locals_2 = (int) intValue.invoke(locals[2]); + int locals_3 = (int) intValue.invoke(locals[3]); + if (locals_2 != 0){ + throw new RuntimeException("Expected locals_2 == 0"); + } + return l; // Don't want l to become a dead var + } + + private static void setupReflectionStatics() throws Throwable { + Class liveStackFrameClass = Class.forName("java.lang.LiveStackFrame"); + primitiveValueClass = Class.forName("java.lang.LiveStackFrame$PrimitiveValue"); + + getLocals = liveStackFrameClass.getDeclaredMethod("getLocals"); + getLocals.setAccessible(true); + + intValue = primitiveValueClass.getDeclaredMethod("intValue"); + intValue.setAccessible(true); + + Class stackFrameInfoClass = Class.forName("java.lang.StackFrameInfo"); + memberName = stackFrameInfoClass.getDeclaredField("memberName"); + memberName.setAccessible(true); + offset = stackFrameInfoClass.getDeclaredField("bci"); + offset.setAccessible(true); + getMethodType = Class.forName("java.lang.invoke.MemberName").getDeclaredMethod("getMethodType"); + getMethodType.setAccessible(true); + + Class extendedOptionClass = Class.forName("java.lang.StackWalker$ExtendedOption"); + Method ewsNI = StackWalker.class.getDeclaredMethod("newInstance", Set.class, extendedOptionClass); + ewsNI.setAccessible(true); + Field f = extendedOptionClass.getDeclaredField("LOCALS_AND_OPERANDS"); + f.setAccessible(true); + Object localsAndOperandsOption = f.get(null); + + primitiveType = primitiveValueClass.getDeclaredMethod("type"); + primitiveType.setAccessible(true); + + sw = (StackWalker) ewsNI.invoke(null, java.util.Collections.emptySet(), localsAndOperandsOption); + } + + private static String type(Object o) throws Throwable { + if (primitiveValueClass.isInstance(o)) { + final char c = (char) primitiveType.invoke(o); + return String.valueOf(c); + } else if (o != null) { + return o.getClass().getName(); + } else { + return "null"; + } + } +}