8138815: improve tests CompilerToVM::getStackTraceElement
authortpivovarova
Mon, 16 Nov 2015 19:21:35 +0300
changeset 34212 36bf267af0f8
parent 34211 d25c2fc1e248
child 34213 3f99eccd6ea3
8138815: improve tests CompilerToVM::getStackTraceElement Reviewed-by: kvn
hotspot/test/compiler/jvmci/common/CTVMUtilities.java
hotspot/test/compiler/jvmci/compilerToVM/GetLineNumberTableTest.java
hotspot/test/compiler/jvmci/compilerToVM/GetStackTraceElementTest.java
--- a/hotspot/test/compiler/jvmci/common/CTVMUtilities.java	Tue Nov 24 10:30:23 2015 +0100
+++ b/hotspot/test/compiler/jvmci/common/CTVMUtilities.java	Mon Nov 16 19:21:35 2015 +0300
@@ -23,10 +23,25 @@
 
 package compiler.jvmci.common;
 
+import java.io.IOException;
 import java.lang.reflect.Field;
 import java.lang.reflect.Executable;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Parameter;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.TreeMap;
+
+import jdk.internal.org.objectweb.asm.ClassReader;
+import jdk.internal.org.objectweb.asm.ClassVisitor;
+import jdk.internal.org.objectweb.asm.ClassWriter;
+import jdk.internal.org.objectweb.asm.Label;
+import jdk.internal.org.objectweb.asm.MethodVisitor;
+import jdk.internal.org.objectweb.asm.Opcodes;
+import jdk.internal.org.objectweb.asm.tree.ClassNode;
+import jdk.test.lib.Utils;
 import jdk.vm.ci.code.InstalledCode;
 import jdk.vm.ci.hotspot.CompilerToVMHelper;
 import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
@@ -71,4 +86,73 @@
             this.entryPoint = entryPoint;
         }
     }
+    public static Map<Integer, Integer> getBciToLineNumber(Executable method) {
+        Map<Integer, Integer> lineNumbers = new TreeMap<>();
+        try {
+            ClassReader cr = new ClassReader(method.getDeclaringClass()
+                    .getName());
+            ClassNode cn = new ClassNode();
+            cr.accept(cn, ClassReader.EXPAND_FRAMES);
+
+            Map<Label, Integer> labels = new HashMap<>();
+            ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
+            ClassVisitor cv = new ClassVisitorForLabels(cw, labels, method);
+            cr.accept(cv, ClassReader.EXPAND_FRAMES);
+            labels.forEach((k, v) -> lineNumbers.put(k.getOffset(), v));
+        } catch (IOException e) {
+            throw new Error("TEST BUG " + e, e);
+        }
+        boolean isEmptyMethod = Modifier.isAbstract(method.getModifiers())
+                || Modifier.isNative(method.getModifiers());
+        if (lineNumbers.isEmpty() && !isEmptyMethod) {
+            throw new Error(method + " doesn't contains the line numbers table "
+                    +"(the method marked neither abstract nor native)");
+        }
+        return lineNumbers;
+    }
+
+    private static class ClassVisitorForLabels extends ClassVisitor {
+        private final Map<Label, Integer> lineNumbers;
+        private final String targetName;
+        private final String targetDesc;
+
+        public ClassVisitorForLabels(ClassWriter cw, Map<Label, Integer> lines,
+                                     Executable target) {
+            super(Opcodes.ASM5, cw);
+            this.lineNumbers = lines;
+
+            StringBuilder builder = new StringBuilder("(");
+            for (Parameter parameter : target.getParameters()) {
+                builder.append(Utils.toJVMTypeSignature(parameter.getType()));
+            }
+            builder.append(")");
+            if (target instanceof Constructor) {
+                targetName = "<init>";
+                builder.append("V");
+            } else {
+                targetName = target.getName();
+                builder.append(Utils.toJVMTypeSignature(
+                        ((Method) target).getReturnType()));
+            }
+            targetDesc = builder.toString();
+        }
+
+        @Override
+        public final MethodVisitor visitMethod(int access, String name,
+                                               String desc, String signature,
+                                               String[] exceptions) {
+            MethodVisitor mv = cv.visitMethod(access, name, desc, signature,
+                    exceptions);
+            if (targetDesc.equals(desc) && targetName.equals(name)) {
+                return new MethodVisitor(Opcodes.ASM5, mv) {
+                    @Override
+                    public void visitLineNumber(int i, Label label) {
+                        super.visitLineNumber(i, label);
+                        lineNumbers.put(label, i);
+                    }
+                };
+            }
+            return  mv;
+        }
+    }
 }
--- a/hotspot/test/compiler/jvmci/compilerToVM/GetLineNumberTableTest.java	Tue Nov 24 10:30:23 2015 +0100
+++ b/hotspot/test/compiler/jvmci/compilerToVM/GetLineNumberTableTest.java	Mon Nov 16 19:21:35 2015 +0300
@@ -40,25 +40,11 @@
 import compiler.jvmci.common.testcases.TestCase;
 import jdk.vm.ci.hotspot.CompilerToVMHelper;
 import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
-import jdk.internal.org.objectweb.asm.ClassReader;
-import jdk.internal.org.objectweb.asm.ClassVisitor;
-import jdk.internal.org.objectweb.asm.ClassWriter;
-import jdk.internal.org.objectweb.asm.Label;
-import jdk.internal.org.objectweb.asm.MethodVisitor;
-import jdk.internal.org.objectweb.asm.Opcodes;
-import jdk.internal.org.objectweb.asm.tree.ClassNode;
 import jdk.test.lib.Asserts;
-import jdk.test.lib.Utils;
 
-import java.io.IOException;
-import java.lang.reflect.Constructor;
 import java.lang.reflect.Executable;
-import java.lang.reflect.Method;
-import java.lang.reflect.Parameter;
 import java.util.Arrays;
-import java.util.HashMap;
 import java.util.Map;
-import java.util.TreeMap;
 
 public class GetLineNumberTableTest {
     public static void main(String[] args) {
@@ -80,79 +66,19 @@
     }
 
     public static long[] getExpectedLineNumbers(Executable aMethod) {
-        try {
-            ClassReader cr = new ClassReader(aMethod.getDeclaringClass()
-                    .getName());
-            ClassNode cn = new ClassNode();
-            cr.accept(cn, ClassReader.EXPAND_FRAMES);
-
-            Map<Label, Integer> lineNumbers = new HashMap<>();
-            ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
-            ClassVisitor cv = new ClassVisitorForLabels(cw, lineNumbers,
-                    aMethod);
-            cr.accept(cv, ClassReader.EXPAND_FRAMES);
-
-            long[] result = null;
-            if (!lineNumbers.isEmpty()) {
-                Map<Integer, Integer> labels = new TreeMap<>();
-                lineNumbers.forEach((k, v) -> labels.put(k.getOffset(), v));
-
-                result = new long[2 * labels.size()];
-                int i = 0;
-                for (Integer key : labels.keySet()) {
-                    result[i++] = key.longValue();
-                    result[i++] = labels.get(key).longValue();
-                }
+        Map<Integer, Integer> bciToLine = CTVMUtilities
+                .getBciToLineNumber(aMethod);
+        long[] result = null;
+        if (!bciToLine.isEmpty()) {
+            result = new long[2 * bciToLine.size()];
+            int i = 0;
+            for (Integer key : bciToLine.keySet()) {
+                result[i++] = key.longValue();
+                result[i++] = bciToLine.get(key).longValue();
             }
-            // compilerToVM::getLineNumberTable returns null in case empty table
-            return result;
-        } catch (IOException e) {
-            throw new Error("TEST BUG " + e, e);
         }
+        // compilerToVM::getLineNumberTable returns null in case empty table
+        return result;
     }
 
-    private static class ClassVisitorForLabels extends ClassVisitor {
-        private final Map<Label, Integer> lineNumbers;
-        private final String targetName;
-        private final String targetDesc;
-
-        public ClassVisitorForLabels(ClassWriter cw, Map<Label, Integer> lines,
-                                     Executable target) {
-            super(Opcodes.ASM5, cw);
-            this.lineNumbers = lines;
-
-            StringBuilder builder = new StringBuilder("(");
-            for (Parameter parameter : target.getParameters()) {
-                builder.append(Utils.toJVMTypeSignature(parameter.getType()));
-            }
-            builder.append(")");
-            if (target instanceof Constructor) {
-                targetName = "<init>";
-                builder.append("V");
-            } else {
-                targetName = target.getName();
-                builder.append(Utils.toJVMTypeSignature(
-                        ((Method) target).getReturnType()));
-            }
-            targetDesc = builder.toString();
-        }
-
-        @Override
-        public final MethodVisitor visitMethod(int access, String name,
-                                               String desc, String signature,
-                                               String[] exceptions) {
-            MethodVisitor mv = cv.visitMethod(access, name, desc, signature,
-                    exceptions);
-            if (targetDesc.equals(desc) && targetName.equals(name)) {
-                return new MethodVisitor(Opcodes.ASM5, mv) {
-                    @Override
-                    public void visitLineNumber(int i, Label label) {
-                        super.visitLineNumber(i, label);
-                        lineNumbers.put(label, i);
-                    }
-                };
-            }
-            return  mv;
-        }
-    }
 }
--- a/hotspot/test/compiler/jvmci/compilerToVM/GetStackTraceElementTest.java	Tue Nov 24 10:30:23 2015 +0100
+++ b/hotspot/test/compiler/jvmci/compilerToVM/GetStackTraceElementTest.java	Mon Nov 16 19:21:35 2015 +0300
@@ -41,6 +41,8 @@
 import java.lang.reflect.Modifier;
 import java.util.HashMap;
 import java.util.Map;
+
+import compiler.jvmci.common.testcases.TestCase;
 import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
 import jdk.vm.ci.hotspot.CompilerToVMHelper;
 import jdk.test.lib.Asserts;
@@ -56,22 +58,49 @@
         HotSpotResolvedJavaMethod method = CTVMUtilities
                 .getResolvedMethod(aMethod);
         String className = aMethod.getDeclaringClass().getName();
+        String methodName = aMethod.getName().equals(className)
+                ? "<init>"
+                : aMethod.getName();
+        String fileName = getFileName(className);
+        Map<Integer, Integer> bciWithLineNumber = CTVMUtilities
+                .getBciToLineNumber(aMethod);
+        boolean isNative = Modifier.isNative(aMethod.getModifiers());
+        int lineNumber = -1;
+        for (int bci : bcis) {
+            StackTraceElement ste = CompilerToVMHelper
+                    .getStackTraceElement(method, bci);
+            Asserts.assertNotNull(ste, aMethod + " : got null StackTraceElement"
+                    + " at bci " + bci);
+            Asserts.assertEQ(className, ste.getClassName(), aMethod
+                    + " : unexpected class name");
+            Asserts.assertEQ(fileName, ste.getFileName(), aMethod
+                    + " : unexpected filename");
+            Asserts.assertEQ(methodName, ste.getMethodName(), aMethod
+                    + " : unexpected method name");
+            Asserts.assertEQ(isNative, ste.isNativeMethod(), aMethod
+                    + " : unexpected 'isNative' value");
+            if (bciWithLineNumber.size() > 0) {
+                if (bciWithLineNumber.containsKey(bci)) {
+                    lineNumber = bciWithLineNumber.get(bci);
+                }
+                Asserts.assertEQ(lineNumber, ste.getLineNumber(), aMethod
+                        + " : unexpected line number");
+            } else {
+                // native and abstract function
+                Asserts.assertLT(0, ste.getLineNumber(),
+                        aMethod + " : unexpected line number for abstract "
+                                + "or native method");
+            }
+        }
+
+    }
+
+    private static String getFileName(String className) {
         int lastDot = className.lastIndexOf('.');
         int firstDol = className.contains("$")
                 ? className.indexOf('$')
                 : className.length();
-        String fileName = className.substring(lastDot + 1, firstDol) + ".java";
-        for (int bci : bcis) {
-            StackTraceElement ste = CompilerToVMHelper
-                    .getStackTraceElement(method, bci);
-            Asserts.assertNotNull(ste);
-            Asserts.assertEQ(ste.getClassName(), className);
-            Asserts.assertEQ(ste.getFileName(), fileName);
-            Asserts.assertEQ(ste.getMethodName(), aMethod.getName());
-            Asserts.assertEQ(ste.isNativeMethod(), Modifier
-                    .isNative(aMethod.getModifiers()));
-        }
-
+        return className.substring(lastDot + 1, firstDol) + ".java";
     }
 
     private static Map<Executable, int[]> createTestCases() {
@@ -86,6 +115,13 @@
             aMethod = aClass.getDeclaredMethod("dummyEmptyFunction");
             bci = new int[] {0};
             testCases.put(aMethod, bci);
+
+            aMethod = aClass.getDeclaredMethod("nativeFunction");
+            bci = new int[] {0};
+            testCases.put(aMethod, bci);
+
+            TestCase.getAllExecutables()
+                    .forEach(c -> testCases.put(c, new int[] {0}));
         } catch (NoSuchMethodException e) {
             throw new Error("TEST BUG : test method not found", e);
         }
@@ -102,5 +138,7 @@
         }
 
         public void dummyEmptyFunction() {}
+
+        public native void nativeFunction();
     }
 }