view graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/jvmci/HotSpotMethodHandleAccessProvider.java @ 21536:7fed589ff982

remove documentation about extended bytecodes
author Doug Simon <doug.simon@oracle.com>
date Mon, 25 May 2015 11:06:22 +0200
parents de0cf192779c
children
line wrap: on
line source

/*
 * 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.graal.hotspot.jvmci;

import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
import static com.oracle.graal.hotspot.jvmci.HotSpotResolvedJavaType.*;
import static com.oracle.graal.hotspot.jvmci.HotSpotResolvedObjectTypeImpl.*;

import com.oracle.graal.api.meta.*;
import com.oracle.graal.compiler.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 GraalInternalError.shouldNotReachHere();
            }
        }
    }

    @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());
    }
}