diff graal/com.oracle.jvmci.hotspot/src/com/oracle/jvmci/hotspot/HotSpotMethodHandleAccessProvider.java @ 21551:5324104ac4f3

moved com.oracle.graal.hotspot.jvmci classes to com.oracle.jvmci.hotspot module (JBS:GRAAL-53)
author Doug Simon <doug.simon@oracle.com>
date Tue, 26 May 2015 17:13:37 +0200
parents graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodHandleAccessProvider.java@93c50cefb9e8
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.jvmci.hotspot/src/com/oracle/jvmci/hotspot/HotSpotMethodHandleAccessProvider.java	Tue May 26 17:13:37 2015 +0200
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.jvmci.hotspot;
+
+import static com.oracle.jvmci.hotspot.HotSpotJVMCIRuntime.*;
+import static com.oracle.jvmci.hotspot.HotSpotResolvedJavaType.*;
+import static com.oracle.jvmci.hotspot.HotSpotResolvedObjectTypeImpl.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.jvmci.common.*;
+
+public class HotSpotMethodHandleAccessProvider implements MethodHandleAccessProvider, HotSpotProxified {
+
+    private final ConstantReflectionProvider constantReflection;
+
+    public HotSpotMethodHandleAccessProvider(ConstantReflectionProvider constantReflection) {
+        this.constantReflection = constantReflection;
+    }
+
+    /**
+     * Lazy initialization to break class initialization cycle. Field and method lookup is only
+     * possible after the {@link HotSpotJVMCIRuntime} is fully initialized.
+     */
+    static class LazyInitialization {
+        static final ResolvedJavaField methodHandleFormField;
+        static final ResolvedJavaField lambdaFormVmentryField;
+        static final ResolvedJavaMethod lambdaFormCompileToBytecodeMethod;
+        static final ResolvedJavaField memberNameVmtargetField;
+
+        /**
+         * Search for an instance field with the given name in a class.
+         *
+         * @param className name of the class to search in
+         * @param fieldName name of the field to be searched
+         * @return resolved java field
+         * @throws ClassNotFoundException
+         */
+        private static ResolvedJavaField findFieldInClass(String className, String fieldName) throws ClassNotFoundException {
+            Class<?> clazz = Class.forName(className);
+            ResolvedJavaType type = fromClass(clazz);
+            ResolvedJavaField[] fields = type.getInstanceFields(false);
+            for (ResolvedJavaField field : fields) {
+                if (field.getName().equals(fieldName)) {
+                    return field;
+                }
+            }
+            return null;
+        }
+
+        private static ResolvedJavaMethod findMethodInClass(String className, String methodName) throws ClassNotFoundException {
+            Class<?> clazz = Class.forName(className);
+            HotSpotResolvedObjectTypeImpl type = fromObjectClass(clazz);
+            ResolvedJavaMethod result = null;
+            for (ResolvedJavaMethod method : type.getDeclaredMethods()) {
+                if (method.getName().equals(methodName)) {
+                    assert result == null : "more than one method found: " + className + "." + methodName;
+                    result = method;
+                }
+            }
+            assert result != null : "method not found: " + className + "." + methodName;
+            return result;
+        }
+
+        static {
+            try {
+                methodHandleFormField = findFieldInClass("java.lang.invoke.MethodHandle", "form");
+                lambdaFormVmentryField = findFieldInClass("java.lang.invoke.LambdaForm", "vmentry");
+                lambdaFormCompileToBytecodeMethod = findMethodInClass("java.lang.invoke.LambdaForm", "compileToBytecode");
+                memberNameVmtargetField = findFieldInClass("java.lang.invoke.MemberName", "vmtarget");
+            } catch (Throwable ex) {
+                throw new JVMCIError(ex);
+            }
+        }
+    }
+
+    @Override
+    public IntrinsicMethod lookupMethodHandleIntrinsic(ResolvedJavaMethod method) {
+        int intrinsicId = ((HotSpotResolvedJavaMethodImpl) method).intrinsicId();
+        if (intrinsicId != 0) {
+            return getMethodHandleIntrinsic(intrinsicId);
+        }
+        return null;
+    }
+
+    public static IntrinsicMethod getMethodHandleIntrinsic(int intrinsicId) {
+        HotSpotVMConfig config = runtime().getConfig();
+        if (intrinsicId == config.vmIntrinsicInvokeBasic) {
+            return IntrinsicMethod.INVOKE_BASIC;
+        } else if (intrinsicId == config.vmIntrinsicLinkToInterface) {
+            return IntrinsicMethod.LINK_TO_INTERFACE;
+        } else if (intrinsicId == config.vmIntrinsicLinkToSpecial) {
+            return IntrinsicMethod.LINK_TO_SPECIAL;
+        } else if (intrinsicId == config.vmIntrinsicLinkToStatic) {
+            return IntrinsicMethod.LINK_TO_STATIC;
+        } else if (intrinsicId == config.vmIntrinsicLinkToVirtual) {
+            return IntrinsicMethod.LINK_TO_VIRTUAL;
+        }
+        return null;
+    }
+
+    @Override
+    public ResolvedJavaMethod resolveInvokeBasicTarget(JavaConstant methodHandle, boolean forceBytecodeGeneration) {
+        if (methodHandle.isNull()) {
+            return null;
+        }
+
+        /* Load non-public field: LambdaForm MethodHandle.form */
+        JavaConstant lambdaForm = constantReflection.readFieldValue(LazyInitialization.methodHandleFormField, methodHandle);
+        if (lambdaForm.isNull()) {
+            return null;
+        }
+
+        JavaConstant memberName;
+        if (forceBytecodeGeneration) {
+            /* Invoke non-public method: MemberName LambdaForm.compileToBytecode() */
+            memberName = LazyInitialization.lambdaFormCompileToBytecodeMethod.invoke(lambdaForm, new JavaConstant[0]);
+        } else {
+            /* Load non-public field: MemberName LambdaForm.vmentry */
+            memberName = constantReflection.readFieldValue(LazyInitialization.lambdaFormVmentryField, lambdaForm);
+        }
+        return getTargetMethod(memberName);
+    }
+
+    @Override
+    public ResolvedJavaMethod resolveLinkToTarget(JavaConstant memberName) {
+        return getTargetMethod(memberName);
+    }
+
+    /**
+     * Returns the {@link ResolvedJavaMethod} for the vmtarget of a java.lang.invoke.MemberName.
+     */
+    private ResolvedJavaMethod getTargetMethod(JavaConstant memberName) {
+        if (memberName.isNull()) {
+            return null;
+        }
+
+        /* Load injected field: JVM_Method* MemberName.vmtarget */
+        JavaConstant vmtarget = constantReflection.readFieldValue(LazyInitialization.memberNameVmtargetField, memberName);
+        /* Create a method from the vmtarget method pointer. */
+        return HotSpotResolvedJavaMethodImpl.fromMetaspace(vmtarget.asLong());
+    }
+}