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;
}
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;
}
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;
}
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;
}
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;
}
Aggregations