changeset 14063:00da8e787d47

Interpreter: Don't try to support reflective invocation of interpreted constructors from native; this allows us to turn back on verification, which found some codegen bugs. Failing tests: 2.
author briangoetz
date Mon, 13 Jun 2016 17:51:37 -0400
parents 546310bd4ee5
children 0f7a9b8602e5
files interpreter/build.xml interpreter/src/valhalla/interpreter/Interpreter.java interpreter/src/valhalla/interpreter/OpcodeHandler.java interpreter/src/valhalla/interpreter/ProxyClassBuilder.java
diffstat 4 files changed, 30 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/interpreter/build.xml	Sun Jun 12 18:39:17 2016 -0400
+++ b/interpreter/build.xml	Mon Jun 13 17:51:37 2016 -0400
@@ -71,7 +71,6 @@
         <testng classpathref="test.class.path"
                 haltOnFailure="true" verbose="2">
             <classfileset dir="${interpreter.test.classes}" includes="**/*.class" />
-            <jvmarg value="-Xverify:none" />
             <jvmarg value="-ea" />
             <jvmarg value="-esa" />
         </testng>
--- a/interpreter/src/valhalla/interpreter/Interpreter.java	Sun Jun 12 18:39:17 2016 -0400
+++ b/interpreter/src/valhalla/interpreter/Interpreter.java	Mon Jun 13 17:51:37 2016 -0400
@@ -379,7 +379,7 @@
                 cs = (CallSite) interpretOrExecute(f, bsm, args).getReturnValueOrThrow();
                 if (!cs.getTarget().type().equals(methodType))
                     throw new BootstrapMethodError("wrong type of call site: "+cs.getTarget().type());
-            } catch (InterpreterError ex) {
+            } catch (AssertionError|InterpreterError ex) {
                 throw ex;
             } catch (Throwable ex) {
                 cs = new FailedCallSite(methodType, ex);
--- a/interpreter/src/valhalla/interpreter/OpcodeHandler.java	Sun Jun 12 18:39:17 2016 -0400
+++ b/interpreter/src/valhalla/interpreter/OpcodeHandler.java	Mon Jun 13 17:51:37 2016 -0400
@@ -82,7 +82,7 @@
             Object res;
             try {
                 res = fn.runOrThrow();
-            } catch (InterpreterError ex) {
+            } catch (AssertionError|InterpreterError ex) {
                 throw ex;   // do not wrap this particular error; pass it to interpreter framework
             } catch (Throwable ex) {
                 return exception(ex);
--- a/interpreter/src/valhalla/interpreter/ProxyClassBuilder.java	Sun Jun 12 18:39:17 2016 -0400
+++ b/interpreter/src/valhalla/interpreter/ProxyClassBuilder.java	Mon Jun 13 17:51:37 2016 -0400
@@ -37,6 +37,7 @@
 
 import static jdk.internal.org.objectweb.asm.ClassWriter.COMPUTE_FRAMES;
 import static jdk.internal.org.objectweb.asm.ClassWriter.COMPUTE_MAXS;
+import static jdk.internal.org.objectweb.asm.Opcodes.ACC_ABSTRACT;
 import static jdk.internal.org.objectweb.asm.Opcodes.INVOKESPECIAL;
 import static jdk.internal.org.objectweb.asm.Opcodes.INVOKESTATIC;
 
@@ -59,6 +60,7 @@
 public class ProxyClassBuilder {
     private static final String INTERPRETER_CLASS = "valhalla/interpreter/Interpreter";
     private static final String CALLBACK_DESC = "(Ljava/lang/Class;ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/Object;";
+    public static final String INIT_NAME = "<init>";
     public static final String CLINIT_NAME = "<clinit>";
     public static final String FAKE_INIT_NAME = "__clinit__";
     public static final String CLINIT_DESC = "()V";
@@ -92,7 +94,28 @@
         if (methodName.equals(CLINIT_NAME) && desc.equals(CLINIT_DESC))
             return this;
 
+        // Make constructors always throw; this is unfortunate, because it means that
+        // we can't instantiate intepreted classes reflectively from native code, but
+        // otherwise the verifier balks at our translation strategy
+        if (methodName.equals(INIT_NAME)) {
+            MethodVisitor mv = cw.visitMethod(access, methodName, desc, null, null);
+            GeneratorAdapter ga = new GeneratorAdapter(mv, access, methodName, desc);
+            ga.newInstance(Type.getObjectType("java/lang/UnsupportedOperationException"));
+            ga.dup();
+            ga.invokeConstructor(Type.getObjectType("java/lang/UnsupportedOperationException"), new Method(INIT_NAME, "()V"));
+            ga.throwException();
+            ga.returnValue();
+            ga.endMethod();
+            return this;
+        }
+
         MethodVisitor mv = cw.visitMethod(access, methodName, desc, null, null);
+        if ((access & ACC_ABSTRACT) != 0) {
+            // Abstract methods get no code attribute
+            mv.visitEnd();
+            return this;
+        }
+
         Type methodType = Type.getMethodType(desc);
         GeneratorAdapter ga = new GeneratorAdapter(mv, access, methodName, desc);
         mv.visitCode();
@@ -125,6 +148,11 @@
         }
 
         ga.invokeStatic(Type.getObjectType(INTERPRETER_CLASS), new Method("callback", CALLBACK_DESC));
+        if (methodType.getReturnType().getSort() == Type.OBJECT || methodType.getReturnType().getSort() == Type.ARRAY)
+            ga.checkCast(methodType.getReturnType());
+        else if (methodType.getReturnType().getSort() != Type.VOID) {
+            ga.unbox(methodType.getReturnType());
+        }
         ga.returnValue();
         ga.endMethod();