changeset 14065:7e5201fad2a2

Interpreter: more reduction on ASM-dependence -- parse method signatures directly rather than using Type.
author briangoetz
date Thu, 16 Jun 2016 14:59:12 -0400
parents 0f7a9b8602e5
children 14f4659703c8 00a9cf4de5b4
files interpreter/build.xml interpreter/src/valhalla/interpreter/Frame.java interpreter/src/valhalla/interpreter/Interpreter.java interpreter/src/valhalla/interpreter/StandardInterpreter.java
diffstat 4 files changed, 53 insertions(+), 13 deletions(-) [+]
line wrap: on
line diff
--- a/interpreter/build.xml	Wed Jun 15 18:07:49 2016 +0100
+++ b/interpreter/build.xml	Thu Jun 16 14:59:12 2016 -0400
@@ -69,7 +69,8 @@
 
     <target name="test" depends="compile,compile-test">
         <testng classpathref="test.class.path"
-                haltOnFailure="true" verbose="2">
+                haltOnFailure="true" verbose="2"
+                usedefaultlisteners="false" listeners="org.testng.reporters.jq.Main">
             <classfileset dir="${interpreter.test.classes}" includes="**/*.class" />
             <jvmarg value="-ea" />
             <jvmarg value="-esa" />
--- a/interpreter/src/valhalla/interpreter/Frame.java	Wed Jun 15 18:07:49 2016 +0100
+++ b/interpreter/src/valhalla/interpreter/Frame.java	Thu Jun 16 14:59:12 2016 -0400
@@ -24,8 +24,6 @@
  */
 package valhalla.interpreter;
 
-import jdk.internal.org.objectweb.asm.Type;
-
 import java.lang.invoke.MethodHandles.Lookup;
 
 import static valhalla.interpreter.Frame.SlotKind.*;
@@ -309,11 +307,10 @@
     }
 
     public Object[] popArgs(String methodDesc) {
-        Type type = Type.getType(methodDesc);
-        Type[] argTypes = type.getArgumentTypes();
+        String[] argTypes = interpreter.methodArgTypes(methodDesc);
         Object[] res = new Object[argTypes.length];
         for (int i = res.length - 1; i >= 0; i--) {
-            res[i] = popBoxed(argTypes[i].getDescriptor());
+            res[i] = popBoxed(argTypes[i]);
         }
         return res;
     }
@@ -364,13 +361,12 @@
     }
 
     public void storeArgs(String methodDesc, Object[] args) {
-        Type type = Type.getType(methodDesc);
-        Type[] argTypes = type.getArgumentTypes();
+        String[] argTypes = interpreter.methodArgTypes(methodDesc);
         assert argTypes.length == args.length;
         int slot = 0;
         for (int i = 0; i < args.length; i++) {
             Object arg = args[i];
-            String typeDesc = argTypes[i].getDescriptor();
+            String typeDesc = argTypes[i];
             if (typeDesc.equals("J")) {
                 lstore(slot, (Long) arg);
                 slot += 2;
--- a/interpreter/src/valhalla/interpreter/Interpreter.java	Wed Jun 15 18:07:49 2016 +0100
+++ b/interpreter/src/valhalla/interpreter/Interpreter.java	Thu Jun 16 14:59:12 2016 -0400
@@ -25,7 +25,6 @@
 package valhalla.interpreter;
 
 import jdk.internal.org.objectweb.asm.Opcodes;
-import jdk.internal.org.objectweb.asm.Type;
 import sun.misc.Resource;
 import sun.misc.URLClassPath;
 import valhalla.interpreter.OpcodeHandler.HandlerAction;
@@ -36,8 +35,6 @@
 import java.lang.invoke.MethodHandles.Lookup;
 import java.lang.reflect.Array;
 import java.lang.reflect.Field;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.net.URL;
 import java.net.URLClassLoader;
@@ -50,6 +47,8 @@
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.function.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 import static com.sun.tools.classfile.ConstantPool.*;
 import static java.lang.invoke.MethodHandleInfo.*;
@@ -63,6 +62,8 @@
  * @author John Rose
  */
 public abstract class Interpreter {
+    protected final static Pattern methodDescPattern = Pattern.compile("\\(([^\\)]*)\\)(.*)");
+
     boolean TRACING = false;
 
     private final Class<?>[] primClasses = new Class<?>[16];
@@ -90,6 +91,8 @@
 
     public abstract String opcodeToString(int opcode);
 
+    public abstract Pattern descriptorPattern();
+
     public void setEventFilter(Set<InterpreterEvent.Kind> eventFilter) {
         this.eventFilter = eventFilter;
     }
@@ -173,6 +176,38 @@
         }
     }
 
+    protected boolean validTypeDescriptor(String desc) {
+        return descriptorPattern().matcher(desc).matches();
+    }
+
+    protected String methodReturnType(String methodDesc) {
+        Matcher matcher = methodDescPattern.matcher(methodDesc);
+        if (!matcher.matches())
+            throw new InterpreterError("Error parsing method descriptor " + methodDesc);
+        String ret = matcher.group(2);
+        if (!descriptorPattern().matcher(ret).matches())
+            throw new InterpreterError(String.format("Error parsing method descriptor; %s is not a valid descriptor", ret));
+        return ret;
+
+    }
+
+    protected String[] methodArgTypes(String methodDesc) {
+        Matcher matcher = methodDescPattern.matcher(methodDesc);
+        if (!matcher.matches())
+            throw new InterpreterError("Error parsing method descriptor " + methodDesc);
+        String args = matcher.group(1);
+        ArrayList<String> list = new ArrayList<>();
+        int start = 0;
+        while (start < args.length()) {
+            Matcher mm = descriptorPattern().matcher(args);
+            if (!mm.find(start) || mm.start() != start)
+                throw new InterpreterError("Error parsing method descriptor " + methodDesc);
+            list.add(args.substring(start, mm.end()));
+            start = mm.end();
+        }
+        return list.toArray(new String[list.size()]);
+    }
+
     protected Class<?> toPrimClass(int basicType) throws InterpreterError {
         return Objects.requireNonNull(primClasses[basicType]);
     }
@@ -193,7 +228,7 @@
         Object[] args = f.popArgs(type.toMethodDescriptorString());
         if (opcodeDoesNullCheck(f.curOpcode()) && args[0] == null)
             return npe();
-        f.expectResult(Type.getType(type.toMethodDescriptorString()).getReturnType().getDescriptor());
+        f.expectResult(methodReturnType(type.toMethodDescriptorString()));
         HandlerAction action = interpretOrExecute(f, resolved, args);
         return takeRetOrException(f, action);
     }
--- a/interpreter/src/valhalla/interpreter/StandardInterpreter.java	Wed Jun 15 18:07:49 2016 +0100
+++ b/interpreter/src/valhalla/interpreter/StandardInterpreter.java	Thu Jun 16 14:59:12 2016 -0400
@@ -25,6 +25,7 @@
 package valhalla.interpreter;
 
 import java.io.IOException;
+import java.util.regex.Pattern;
 
 import com.sun.tools.classfile.Opcode;
 
@@ -45,6 +46,8 @@
  * @author Brian Goetz
  */
 public class StandardInterpreter extends Interpreter {
+    private static final Pattern DESCRIPTOR_PATTERN = Pattern.compile("\\[*(I|J|D|F|C|S|B|Z|V|L[^;]*;)");
+
     private final OpcodeHandler[] handlers = new OpcodeHandler[255];
     private final int[] opcodeLen = new int[255];
 
@@ -86,6 +89,11 @@
         return Opcode.get(opcode).name();
     }
 
+    @Override
+    public Pattern descriptorPattern() {
+        return DESCRIPTOR_PATTERN;
+    }
+
     private void opcode(int opcode, OpcodeHandler handler) {
         opcode(opcode, 0, handler);
     }