Search in sources :

Example 1 with VMLangAccess

use of com.ibm.oti.vm.VMLangAccess in project openj9 by eclipse.

the class StructuralComparator method resolveInvokeDynamic.

@SuppressWarnings("unused")
private static final MethodHandle resolveInvokeDynamic(long j9class, String name, String methodDescriptor, long bsmData) throws Throwable {
    MethodHandle result = null;
    MethodType type = null;
    try {
        VMLangAccess access = VM.getVMLangAccess();
        Object internalRamClass = access.createInternalRamClass(j9class);
        Class<?> classObject = null;
        if (JITHELPERS.is32Bit()) {
            classObject = JITHELPERS.getClassFromJ9Class32((int) j9class);
        } else {
            classObject = JITHELPERS.getClassFromJ9Class64(j9class);
        }
        Objects.requireNonNull(classObject);
        type = MethodType.vmResolveFromMethodDescriptorString(methodDescriptor, access.getClassloader(classObject), null);
        int bsmIndex = UNSAFE.getShort(bsmData);
        int bsmArgCount = UNSAFE.getShort(bsmData + BSM_ARGUMENT_COUNT_OFFSET);
        long bsmArgs = bsmData + BSM_ARGUMENTS_OFFSET;
        MethodHandle bsm = getCPMethodHandleAt(internalRamClass, bsmIndex);
        if (null == bsm) {
            // $NON-NLS-1$
            throw new NullPointerException(Msg.getString("K05cd", classObject.toString(), bsmIndex));
        }
        Object[] staticArgs = new Object[BSM_OPTIONAL_ARGUMENTS_START_INDEX + bsmArgCount];
        /* Mandatory arguments */
        staticArgs[BSM_LOOKUP_ARGUMENT_INDEX] = new MethodHandles.Lookup(classObject, false);
        staticArgs[BSM_NAME_ARGUMENT_INDEX] = name;
        staticArgs[BSM_TYPE_ARGUMENT_INDEX] = type;
        /* Static optional arguments */
        /* internalRamClass is not a j.l.Class object but the ConstantPool natives know how to
			 * get the internal constantPool from the j9class
			 */
        ConstantPool cp = access.getConstantPool(internalRamClass);
        /* Check if we need to treat the last parameter specially when handling primitives.
			 * The type of the varargs array will determine how primitive ints from the constantpool
			 * get boxed: {Boolean, Byte, Short, Character or Integer}.
			 */
        boolean treatLastArgAsVarargs = bsm.isVarargsCollector();
        Class<?> varargsComponentType = bsm.type.lastParameterType().getComponentType();
        int bsmTypeArgCount = bsm.type.parameterCount();
        for (int i = 0; i < bsmArgCount; i++) {
            int staticArgIndex = BSM_OPTIONAL_ARGUMENTS_START_INDEX + i;
            short index = UNSAFE.getShort(bsmArgs + (i * BSM_ARGUMENT_SIZE));
            int cpType = getCPTypeAt(internalRamClass, index);
            Object cpEntry = null;
            switch(cpType) {
                case 1:
                    cpEntry = cp.getClassAt(index);
                    if (cpEntry == null) {
                        throw throwNoClassDefFoundError(classObject, index);
                    }
                    break;
                case 2:
                    cpEntry = cp.getStringAt(index);
                    break;
                case 3:
                    {
                        int cpValue = cp.getIntAt(index);
                        Class<?> argClass;
                        if (treatLastArgAsVarargs && (staticArgIndex >= (bsmTypeArgCount - 1))) {
                            argClass = varargsComponentType;
                        } else {
                            argClass = bsm.type.parameterType(staticArgIndex);
                        }
                        if (argClass == Short.TYPE) {
                            cpEntry = (short) cpValue;
                        } else if (argClass == Boolean.TYPE) {
                            cpEntry = cpValue == 0 ? Boolean.FALSE : Boolean.TRUE;
                        } else if (argClass == Byte.TYPE) {
                            cpEntry = (byte) cpValue;
                        } else if (argClass == Character.TYPE) {
                            cpEntry = (char) cpValue;
                        } else {
                            cpEntry = cpValue;
                        }
                        break;
                    }
                case 4:
                    cpEntry = cp.getFloatAt(index);
                    break;
                case 5:
                    cpEntry = cp.getLongAt(index);
                    break;
                case 6:
                    cpEntry = cp.getDoubleAt(index);
                    break;
                case 13:
                    cpEntry = getCPMethodTypeAt(internalRamClass, index);
                    break;
                case 14:
                    cpEntry = getCPMethodHandleAt(internalRamClass, index);
                    break;
                default:
            }
            // Implicit NPE
            cpEntry.getClass();
            staticArgs[staticArgIndex] = cpEntry;
        }
        /* Take advantage of the per-MH asType cache */
        CallSite cs = null;
        switch(staticArgs.length) {
            case 3:
                cs = (CallSite) bsm.invoke(staticArgs[0], staticArgs[1], staticArgs[2]);
                break;
            case 4:
                cs = (CallSite) bsm.invoke(staticArgs[0], staticArgs[1], staticArgs[2], staticArgs[3]);
                break;
            case 5:
                cs = (CallSite) bsm.invoke(staticArgs[0], staticArgs[1], staticArgs[2], staticArgs[3], staticArgs[4]);
                break;
            case 6:
                cs = (CallSite) bsm.invoke(staticArgs[0], staticArgs[1], staticArgs[2], staticArgs[3], staticArgs[4], staticArgs[5]);
                break;
            case 7:
                cs = (CallSite) bsm.invoke(staticArgs[0], staticArgs[1], staticArgs[2], staticArgs[3], staticArgs[4], staticArgs[5], staticArgs[6]);
                break;
            default:
                cs = (java.lang.invoke.CallSite) bsm.invokeWithArguments(staticArgs);
                break;
        }
        if (cs != null) {
            MethodType callsiteType = cs.type();
            if (callsiteType != type) {
                throw WrongMethodTypeException.newWrongMethodTypeException(type, callsiteType);
            }
            result = cs.dynamicInvoker();
        }
    } catch (Throwable e) {
        /*[IF Sidecar19-SE]*/
        if (e instanceof Error) {
            throw e;
        }
        if (type == null) {
            throw new BootstrapMethodError(e);
        }
        /* create an exceptionHandle with appropriate drop adapter and install that */
        try {
            MethodHandle thrower = MethodHandles.throwException(type.returnType(), BootstrapMethodError.class);
            MethodHandle constructor = MethodHandles.Lookup.IMPL_LOOKUP.findConstructor(BootstrapMethodError.class, MethodType.methodType(void.class, Throwable.class));
            result = MethodHandles.foldArguments(thrower, constructor.bindTo(e));
            result = MethodHandles.dropArguments(result, 0, type.parameterList());
        } catch (IllegalAccessException iae) {
            throw new Error(iae);
        } catch (NoSuchMethodException nsme) {
            throw new Error(nsme);
        }
    }
    return result;
}
Also used : VMLangAccess(com.ibm.oti.vm.VMLangAccess) Lookup(java.lang.invoke.MethodHandles.Lookup) ConstantPool(sun.reflect.ConstantPool)

Example 2 with VMLangAccess

use of com.ibm.oti.vm.VMLangAccess in project openj9 by eclipse.

the class MethodHandleCache method getCache.

/**
 * Get the MethodHandle cache for a given class.
 * If one doesn't exist, it will be created.
 *
 * @param clazz the Class that MHs are being cached on
 * @return the MethodHandleCache object for that class
 */
public static MethodHandleCache getCache(Class<?> clazz) {
    VMLangAccess vma = MethodHandles.Lookup.getVMLangAccess();
    MethodHandleCache cache = (MethodHandleCache) vma.getMethodHandleCache(clazz);
    if (null == cache) {
        cache = new MethodHandleCache(clazz);
        cache = (MethodHandleCache) vma.setMethodHandleCache(clazz, cache);
    }
    return cache;
}
Also used : VMLangAccess(com.ibm.oti.vm.VMLangAccess)

Example 3 with VMLangAccess

use of com.ibm.oti.vm.VMLangAccess in project openj9 by eclipse.

the class SecurityFrameInjector method penetrateSecurityFrame.

/*
	 * Attempt to unwrap a MethodHandle that has been wrapped in a SecurityFrame.
	 * 
	 * @param potentialInjectFrame The wrapped MethodHandle
	 * @param lookup A Lookup object with the same lookup class as the Lookup object used to create the MethodHandle
	 * 
	 * @return The unwrapped MethodHandle if successfully unwrapped, null if not.
	 */
static MethodHandle penetrateSecurityFrame(MethodHandle potentialInjectFrame, Lookup lookup) {
    final MethodType originalMT = potentialInjectFrame.type;
    // SecurityFrames are always represented as:
    // 1) VarargsCollectHandle -> AsTypeHandle -> RBH with bound value being an instance of SecurityFrame
    // 2) AsTypeHandle -> RBH with bound value being an instance of SecurityFrame
    // 3) RBH with bound value being an instance of SecurityFrame if signature is (Object[])Object
    boolean mustBeVarags = false;
    if (potentialInjectFrame.kind == MethodHandle.KIND_VARARGSCOLLECT) {
        mustBeVarags = true;
        potentialInjectFrame = ((VarargsCollectorHandle) potentialInjectFrame).next;
    }
    if (potentialInjectFrame.kind == MethodHandle.KIND_ASTYPE) {
        potentialInjectFrame = ((AsTypeHandle) potentialInjectFrame).next;
    }
    if (potentialInjectFrame.kind == MethodHandle.KIND_FILTERRETURN) {
        potentialInjectFrame = ((FilterReturnHandle) potentialInjectFrame).next;
    }
    if (potentialInjectFrame.kind == MethodHandle.KIND_COLLECT) {
        potentialInjectFrame = ((CollectHandle) potentialInjectFrame).next;
    }
    if (potentialInjectFrame.kind == MethodHandle.KIND_ASTYPE) {
        potentialInjectFrame = ((AsTypeHandle) potentialInjectFrame).next;
    }
    if (potentialInjectFrame.kind == MethodHandle.KIND_FILTERRETURN) {
        potentialInjectFrame = ((FilterReturnHandle) potentialInjectFrame).next;
    }
    if (potentialInjectFrame.kind == MethodHandle.KIND_BOUND) {
        ReceiverBoundHandle rbh = (ReceiverBoundHandle) potentialInjectFrame;
        final Object receiver = rbh.receiver;
        VMLangAccess vma = Lookup.getVMLangAccess();
        ClassLoader rawLoader = vma.getClassloader(receiver.getClass());
        Class<?> injectedSecurityFrame = null;
        synchronized (loaderLock) {
            injectedSecurityFrame = probeLoaderToSecurityFrameMap(rawLoader);
        }
        if ((injectedSecurityFrame == null) || !injectedSecurityFrame.isInstance(receiver)) {
            /* receiver object cannot be an instance of SecurityFrame as its classloader 
				 * doesn't have an injected security frame class
				 */
            return null;
        }
        final Class<?> finalInjectedSecurityFrame = injectedSecurityFrame;
        MethodHandle target = AccessController.doPrivileged(new PrivilegedAction<MethodHandle>() {

            public MethodHandle run() {
                try {
                    // $NON-NLS-1$
                    Field targetField = finalInjectedSecurityFrame.getDeclaredField("target");
                    targetField.setAccessible(true);
                    return (MethodHandle) targetField.get(receiver);
                } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
                    throw (InternalError) new InternalError().initCause(e);
                }
            }
        });
        Class<?> targetAccessClass = AccessController.doPrivileged(new PrivilegedAction<Class<?>>() {

            public Class<?> run() {
                try {
                    // $NON-NLS-1$
                    Field targetField = finalInjectedSecurityFrame.getDeclaredField("accessClass");
                    targetField.setAccessible(true);
                    return (Class<?>) targetField.get(receiver);
                } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
                    throw (InternalError) new InternalError().initCause(e);
                }
            }
        });
        if (lookup.accessMode != MethodHandles.Lookup.INTERNAL_PRIVILEGED) {
            if (targetAccessClass != lookup.accessClass) {
                return null;
            }
        }
        if (target.type == originalMT) {
            if ((target instanceof PrimitiveHandle) && (Lookup.isVarargs(target.getModifiers()) == mustBeVarags)) {
                return target;
            }
        }
    }
    // Not a directHandle - someone added wrapping to it.
    return null;
}
Also used : VMLangAccess(com.ibm.oti.vm.VMLangAccess) Field(java.lang.reflect.Field)

Example 4 with VMLangAccess

use of com.ibm.oti.vm.VMLangAccess in project openj9 by eclipse.

the class Unsafe method defineClass.

/**
 * Creates a class out of a given array of bytes with a ProtectionDomain.
 *
 * @param name binary name of the class, null if the name is not known
 * @param b a byte array of the class data. The bytes should have the format of a
 * 			valid class file as defined by The JVM Spec
 * @param offset offset of the start of the class data in b
 * @param bLength length of the class data
 * @param cl ClassLoader used to load the class being built. If null, the default
 * system ClassLoader will be used
 * @param pd ProtectionDomain for new class
 * @return class created from the byte array and ProtectionDomain parameters
 *
 * @throws NullPointerException if b array of data is null
 * @throws ArrayIndexOutOfBoundsException if bLength is negative
 * @throws IndexOutOfBoundsException if offset + bLength is greater than the
 * length of b
 */
public Class<?> defineClass(String name, byte[] b, int offset, int bLength, ClassLoader cl, ProtectionDomain pd) {
    Objects.requireNonNull(b);
    if (bLength < 0) {
        throw new ArrayIndexOutOfBoundsException();
    }
    Class<?> result = defineClass0(name, b, offset, bLength, cl, pd);
    VMLangAccess access = VM.getVMLangAccess();
    access.addPackageToList(result, cl);
    return result;
}
Also used : VMLangAccess(com.ibm.oti.vm.VMLangAccess)

Example 5 with VMLangAccess

use of com.ibm.oti.vm.VMLangAccess in project openj9 by eclipse.

the class ReceiverBoundHandle method addRelatedMHs.

/*[IF JAVA_SPEC_VERSION >= 15]*/
@Override
boolean addRelatedMHs(List<MethodHandle> relatedMHs) {
    VMLangAccess vma = Lookup.getVMLangAccess();
    ClassLoader rawLoader = vma.getClassloader(receiver.getClass());
    Class<?> injectedSecurityFrame = null;
    synchronized (SecurityFrameInjector.loaderLock) {
        injectedSecurityFrame = SecurityFrameInjector.probeLoaderToSecurityFrameMap(rawLoader);
    }
    if ((injectedSecurityFrame == null) || !injectedSecurityFrame.isInstance(receiver)) {
        /* Receiver object cannot be an instance of SecurityFrame as its classloader 
			 * doesn't have an injected security frame class.
			 */
        return false;
    }
    final Class<?> finalInjectedSecurityFrame = injectedSecurityFrame;
    MethodHandle target = AccessController.doPrivileged(new PrivilegedAction<MethodHandle>() {

        public MethodHandle run() {
            try {
                // $NON-NLS-1$
                Field targetField = finalInjectedSecurityFrame.getDeclaredField("target");
                targetField.setAccessible(true);
                return (MethodHandle) targetField.get(receiver);
            } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
                throw (InternalError) new InternalError().initCause(e);
            }
        }
    });
    if (target.type() == type()) {
        relatedMHs.add(target);
        return true;
    }
    return false;
}
Also used : Field(java.lang.reflect.Field) VMLangAccess(com.ibm.oti.vm.VMLangAccess)

Aggregations

VMLangAccess (com.ibm.oti.vm.VMLangAccess)5 Field (java.lang.reflect.Field)2 Lookup (java.lang.invoke.MethodHandles.Lookup)1 ConstantPool (sun.reflect.ConstantPool)1