/*
* This file is part of the Jikes RVM project (http://jikesrvm.org).
*
* This file is licensed to You under the Eclipse Public License (EPL);
* You may not use this file except in compliance with the License. You
* may obtain a copy of the License at
*
* http://www.opensource.org/licenses/eclipse-1.0.php
*
* See the COPYRIGHT.txt file distributed with this work for information
* regarding copyright ownership.
*/
package java.lang.reflect;
import org.jikesrvm.VM;
import org.jikesrvm.classloader.RVMArray;
import org.jikesrvm.classloader.RVMClass;
import org.jikesrvm.classloader.RVMField;
import org.jikesrvm.classloader.RVMMember;
import org.jikesrvm.classloader.RVMMethod;
import org.jikesrvm.classloader.TypeReference;
import org.jikesrvm.classloader.RVMType;
import org.jikesrvm.objectmodel.ObjectModel;
import org.jikesrvm.runtime.RuntimeEntrypoints;
import org.jikesrvm.runtime.Magic;
import org.jikesrvm.runtime.Reflection;
import org.jikesrvm.runtime.ReflectionBase;
import org.vmmagic.pragma.Inline;
import org.vmmagic.pragma.NoInline;
import org.vmmagic.pragma.Pure;
/**
* Common utilities for Jikes RVM implementations of the java.lang.reflect API
*/
final class VMCommonLibrarySupport {
/* ---- Non-inlined Exception Throwing Methods --- */
/**
* Method just to throw an illegal argument exception without being inlined
*/
@NoInline
private static void throwNewIllegalArgumentException() {
throw new IllegalArgumentException();
}
/**
* Method just to throw an illegal argument exception without being inlined
*/
@NoInline
private static void throwNewIllegalArgumentException(String str) {
throw new IllegalArgumentException(str);
}
/**
* Method just to throw an illegal access exception without being inlined
*/
@NoInline
private static void throwNewIllegalAccessException() throws IllegalAccessException {
throw new IllegalAccessException();
}
/**
* Method just to throw an illegal access exception without being inlined
*/
@NoInline
private static void throwNewIllegalAccessException(RVMMember member, RVMClass accessingClass) throws IllegalAccessException {
throw new IllegalAccessException("Access to " + member + " is denied to " + accessingClass);
}
/**
* Method just to throw an InstantiationException without being inlined
*/
@NoInline
private static void throwNewInstantiationException(String str) throws InstantiationException {
throw new InstantiationException(str);
}
/**
* Method just to throw a NegativeArraySizeException without being inlined
*/
@NoInline
private static void throwNewNegativeArraySizeException() {
throw new NegativeArraySizeException();
}
/**
* Method just to throw an NullPointerException without being inlined
*/
@NoInline
private static void throwNewNullPointerException() {
throw new NullPointerException();
}
/* ---- Array Methods ---- */
/**
* Dynamically create an array of objects.
*
* @param cls guaranteed to be a valid object type
* @param length the length of the array
* @return the new array
* @throws NegativeArraySizeException if dim is negative
* @throws OutOfMemoryError if memory allocation fails
*/
static Object createArray(Class<?> cls, int length)
throws OutOfMemoryError, NegativeArraySizeException {
if (cls == Void.TYPE)
throwNewIllegalArgumentException("Cannot create new array instance for the specified arguments");
// will raise NPE
RVMArray arrayType = java.lang.JikesRVMSupport.getTypeForClass(cls).getArrayTypeForElementType();
if (!arrayType.isInitialized()) {
arrayType.resolve();
arrayType.instantiate();
arrayType.initialize();
}
// will check -ve array size
return RuntimeEntrypoints.resolvedNewArray(length, arrayType);
}
/**
* Dynamically create a multi-dimensional array of objects.
*
* @param cls guaranteed to be a valid object type
* @param dimensions the lengths for the dimensions of the array
* @return the new array
* @throws NegativeArraySizeException if any dimensions is negative
* @throws OutOfMemoryError if memory allocation fails
*/
static Object createArray(Class<?> cls, int[] dimensions)
throws OutOfMemoryError, NegativeArraySizeException {
if (dimensions.length == 0 || cls == Void.TYPE) {
throwNewIllegalArgumentException("Cannot create new array instance for the specified arguments");
}
// will raise NPE
RVMArray arrayType = java.lang.JikesRVMSupport.getTypeForClass(cls).getArrayTypeForElementType();
for (int i = 1; i < dimensions.length; i++) {
arrayType = arrayType.getArrayTypeForElementType();
}
// will check -ve array sizes
return RuntimeEntrypoints.buildMDAHelper(null, dimensions, 0, arrayType);
}
/* ---- General Reflection Support ---- */
/**
* Check to see if a method declared by the accessingClass
* should be allowed to access the argument RVMMember.
* Assumption: member is not public. This trivial case should
* be approved by the caller without needing to call this method.
*/
private static void checkAccess(RVMMember member, RVMClass accessingClass) throws IllegalAccessException {
RVMClass declaringClass = member.getDeclaringClass();
if (member.isPrivate()) {
// access from the declaringClass is allowed
if (accessingClass == declaringClass) return;
} else if (member.isProtected()) {
// access within the package is allowed.
if (declaringClass.getClassLoader() == accessingClass.getClassLoader() && declaringClass.getPackageName().equals(accessingClass.getPackageName())) return;
// access by subclasses is allowed.
for (RVMClass cls = accessingClass; cls != null; cls = cls.getSuperClass()) {
if (accessingClass == declaringClass) return;
}
} else {
// default: access within package is allowed
if (declaringClass.getClassLoader() == accessingClass.getClassLoader() && declaringClass.getPackageName().equals(accessingClass.getPackageName())) return;
}
throwNewIllegalAccessException(member, accessingClass);
}
/* ---- Reflective Method Invocation Support ---- */
@Inline(value = Inline.When.ArgumentsAreConstant, arguments = {2})
static Object invoke(Object receiver, Object[] args, RVMMethod method, Method jlrMethod, RVMClass accessingClass, ReflectionBase invoker)
throws IllegalAccessException, IllegalArgumentException,
ExceptionInInitializerError, InvocationTargetException {
// validate number and types of arguments
if (!Reflection.needsCheckArgs(invoker) || checkArguments(args, method)) {
if (method.isStatic()) {
return invokeStatic(receiver, args, method, jlrMethod, accessingClass, invoker);
} else {
return invokeVirtual(receiver, args, method, jlrMethod, accessingClass, invoker);
}
} else {
Object[] compatibleArgs = makeArgumentsCompatible(args, method);
if (method.isStatic()) {
return invokeStatic(receiver, compatibleArgs, method, jlrMethod, accessingClass, invoker);
} else {
return invokeVirtual(receiver, compatibleArgs, method, jlrMethod, accessingClass, invoker);
}
}
}
@Inline(value = Inline.When.ArgumentsAreConstant, arguments = {2})
private static Object invokeStatic(Object receiver, Object[] args, RVMMethod method, Method jlrMethod, RVMClass accessingClass, ReflectionBase invoker)
throws IllegalAccessException, IllegalArgumentException,
ExceptionInInitializerError, InvocationTargetException {
// Accessibility checks
if (!method.isPublic() && !jlrMethod.isAccessible()) {
checkAccess(method, accessingClass);
}
// Forces initialization of declaring class
RVMClass declaringClass = method.getDeclaringClass();
if (!declaringClass.isInitialized()) {
runClassInitializer(declaringClass);
}
// Invoke method
try {
return Reflection.invoke(method, invoker, receiver, args, true);
} catch (Throwable t) {
throw new InvocationTargetException(t);
}
}
@Inline(value = Inline.When.ArgumentsAreConstant, arguments = {2})
private static Object invokeVirtual(Object receiver, Object[] args, RVMMethod method, Method jlrMethod, RVMClass accessingClass, ReflectionBase invoker)
throws IllegalAccessException, IllegalArgumentException,
ExceptionInInitializerError, InvocationTargetException {
// validate "this" argument
if (receiver == null) {
throwNewNullPointerException();
}
RVMClass declaringClass = method.getDeclaringClass();
if (!isArgumentCompatible(declaringClass, receiver)) {
throwNewIllegalArgumentException();
}
// Accessibility checks
if (!method.isPublic() && !jlrMethod.isAccessible()) {
checkAccess(method, accessingClass);
}
// find the right method to call
RVMClass C = Magic.getObjectType(receiver).asClass();
method = C.findVirtualMethod(method.getName(), method.getDescriptor());
// Invoke method
try {
return Reflection.invoke(method, invoker, receiver, args, false);
} catch (Throwable t) {
throw new InvocationTargetException(t);
}
}
@Inline(value = Inline.When.ArgumentsAreConstant, arguments = {1})
private static boolean checkArguments(Object[] args, RVMMethod method) throws IllegalArgumentException {
TypeReference[] parameterTypes = method.getParameterTypes();
if (((args == null) && (parameterTypes.length != 0)) ||
((args != null) && (args.length != parameterTypes.length))) {
throwNewIllegalArgumentException("argument count mismatch");
}
switch (parameterTypes.length) {
case 6:
if (!isArgumentCompatible(parameterTypes[5].resolve(), args[5])) {
return false;
}
case 5:
if (!isArgumentCompatible(parameterTypes[4].resolve(), args[4])) {
return false;
}
case 4:
if (!isArgumentCompatible(parameterTypes[3].resolve(), args[3])) {
return false;
}
case 3:
if (!isArgumentCompatible(parameterTypes[2].resolve(), args[2])) {
return false;
}
case 2:
if (!isArgumentCompatible(parameterTypes[1].resolve(), args[1])) {
return false;
}
case 1:
if (!isArgumentCompatible(parameterTypes[0].resolve(), args[0])) {
return false;
}
case 0:
return true;
default:
for (int i = 0, n = parameterTypes.length; i < n; ++i) {
if (!isArgumentCompatible(parameterTypes[i].resolve(), args[i])) {
return false;
}
}
return true;
}
}
@Inline(value = Inline.When.ArgumentsAreConstant, arguments = {1})
private static Object[] makeArgumentsCompatible(Object[] args, RVMMethod method) {
TypeReference[] parameterTypes = method.getParameterTypes();
int length = parameterTypes.length;
Object[] newArgs = new Object[length];
switch(length) {
case 6: newArgs[5] = makeArgumentCompatible(parameterTypes[5].peekType(), args[5]);
case 5: newArgs[4] = makeArgumentCompatible(parameterTypes[4].peekType(), args[4]);
case 4: newArgs[3] = makeArgumentCompatible(parameterTypes[3].peekType(), args[3]);
case 3: newArgs[2] = makeArgumentCompatible(parameterTypes[2].peekType(), args[2]);
case 2: newArgs[1] = makeArgumentCompatible(parameterTypes[1].peekType(), args[1]);
case 1: newArgs[0] = makeArgumentCompatible(parameterTypes[0].peekType(), args[0]);
case 0: break;
default: {
for (int i = 0; i < length; ++i) {
newArgs[i] = makeArgumentCompatible(parameterTypes[i].peekType(), args[i]);
}
break;
}
}
return newArgs;
}
@NoInline
private static void runClassInitializer(RVMClass declaringClass) throws ExceptionInInitializerError {
try {
RuntimeEntrypoints.initializeClassForDynamicLink(declaringClass);
} catch (Throwable e) {
throw new ExceptionInInitializerError(e);
}
}
/**
* Make possibly wrapped method argument compatible with expected type
*/
@SuppressWarnings({"UnnecessaryBoxing","PMD.IntegerInstantiation"})
@NoInline
@Pure
private static Object makeArgumentCompatible(RVMType expectedType, Object arg) {
if (expectedType.isPrimitiveType()) {
if (arg instanceof java.lang.Byte) {
if (expectedType.isByteType()) return arg;
if (expectedType.isShortType()) return Short.valueOf((Byte) arg);
if (expectedType.isIntType()) return Integer.valueOf((Byte) arg);
if (expectedType.isLongType()) return Long.valueOf((Byte) arg);
} else if (arg instanceof java.lang.Short) {
if (expectedType.isShortType()) return arg;
if (expectedType.isIntType()) return Integer.valueOf((Short) arg);
if (expectedType.isLongType()) return Long.valueOf((Short) arg);
} else if (arg instanceof java.lang.Character) {
if (expectedType.isCharType()) return arg;
if (expectedType.isIntType()) return Integer.valueOf((Character) arg);
if (expectedType.isLongType()) return Long.valueOf((Character) arg);
} else if (arg instanceof java.lang.Integer) {
if (expectedType.isIntType()) return arg;
if (expectedType.isLongType()) return Long.valueOf((Integer) arg);
} else if (arg instanceof java.lang.Float) {
if (expectedType.isDoubleType()) return Double.valueOf((Float) arg);
}
}
return arg;
}
/**
* Are the 2 arguments compatible? Throw IllegalArgumentException if they
* can't be made compatible.
*/
@Pure
@Inline
private static boolean isArgumentCompatible(RVMType expectedType, Object arg) {
if (expectedType.isPrimitiveType()) {
return isPrimitiveArgumentCompatible(expectedType, arg);
} else {
if (arg == null) return true; // null is always ok
RVMType actualType = ObjectModel.getObjectType(arg);
if (expectedType == actualType ||
expectedType == RVMType.JavaLangObjectType ||
RuntimeEntrypoints.isAssignableWith(expectedType, actualType)) {
return true;
} else {
throwNewIllegalArgumentException();
return false;
}
}
}
/**
* Is a boxed primitive argument compatible with the expected type
*/
@Pure
@Inline
private static boolean isPrimitiveArgumentCompatible(RVMType expectedType, Object arg) {
if (arg instanceof java.lang.Void) {
if (expectedType.isVoidType()) return true;
} else if (arg instanceof java.lang.Boolean) {
if (expectedType.isBooleanType()) return true;
} else if (arg instanceof java.lang.Byte) {
if (expectedType.isByteType()) return true;
if (expectedType.isShortType()) return false;
if (expectedType.isIntType()) return false;
if (expectedType.isLongType()) return false;
} else if (arg instanceof java.lang.Short) {
if (expectedType.isShortType()) return true;
if (expectedType.isIntType()) return false;
if (expectedType.isLongType()) return false;
} else if (arg instanceof java.lang.Character) {
if (expectedType.isCharType()) return true;
if (expectedType.isIntType()) return false;
if (expectedType.isLongType()) return false;
} else if (arg instanceof java.lang.Integer) {
if (expectedType.isIntType()) return true;
if (expectedType.isLongType()) return false;
} else if (arg instanceof java.lang.Long) {
if (expectedType.isLongType()) return true;
} else if (arg instanceof java.lang.Float) {
if (expectedType.isFloatType()) return true;
if (expectedType.isDoubleType()) return false;
} else if (arg instanceof java.lang.Double) {
if (expectedType.isDoubleType()) return true;
}
throwNewIllegalArgumentException();
return false;
}
/* ---- Constructor Support ---- */
/**
* Construct an object from the given constructor args, called from the accessing class
*/
@Inline(value = Inline.When.ArgumentsAreConstant, arguments = {0})
static Object construct(RVMMethod constructor, Constructor<?> cons, Object[] args, RVMClass accessingClass, ReflectionBase invoker)
throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
// Check accessibility
if (!constructor.isPublic() && !cons.isAccessible()) {
checkAccess(constructor, accessingClass);
}
// validate number and types of arguments to constructor
if (Reflection.needsCheckArgs(invoker) && !checkArguments(args, constructor)) {
args = makeArgumentsCompatible(args, constructor);
}
RVMClass cls = constructor.getDeclaringClass();
if (cls.isAbstract()) {
throwNewInstantiationException("Abstract class");
}
// Ensure that the class is initialized
if (!cls.isInitialized()) {
runClassInitializer(cls);
}
// Allocate an uninitialized instance;
Object obj = RuntimeEntrypoints.resolvedNewScalar(cls);
// Run the constructor on the instance.
try {
Reflection.invoke(constructor, invoker, obj, args, true);
} catch (Throwable e) {
throw new InvocationTargetException(e);
}
return obj;
}
/* ---- Constructor/Method Support ---- */
/**
* Convert from "VM" type system to "JDK" type system.
*/
static Class<?>[] typesToClasses(TypeReference[] types) {
Class<?>[] classes = new Class[types.length];
for (int i = 0; i < types.length; i++) {
classes[i] = types[i].resolve().getClassForType();
}
return classes;
}
/* ---- Field Support ---- */
/**
* Check the field in the given object can be read
*/
@Inline(value = Inline.When.ArgumentsAreConstant, arguments = {1})
private static void checkReadAccess(Object obj, RVMField field, Field jlrField, RVMClass accessingClass) throws IllegalAccessException,
IllegalArgumentException,
ExceptionInInitializerError {
RVMClass declaringClass = field.getDeclaringClass();
if (!field.isStatic()) {
if (obj == null) {
throwNewNullPointerException();
}
RVMType objType = ObjectModel.getObjectType(obj);
if (objType != declaringClass && !RuntimeEntrypoints.isAssignableWith(declaringClass, objType)) {
throwNewIllegalArgumentException();
}
}
if (!field.isPublic() && !jlrField.isAccessible()) {
checkAccess(field, accessingClass);
}
if (field.isStatic() && !declaringClass.isInitialized()) {
runClassInitializer(declaringClass);
}
}
/**
* Check the field in the given object can be written to
*/
@Inline(value = Inline.When.ArgumentsAreConstant, arguments = {1})
private static void checkWriteAccess(Object obj, RVMField field, Field jlrField, RVMClass accessingClass) throws IllegalAccessException,
IllegalArgumentException,
ExceptionInInitializerError {
RVMClass declaringClass = field.getDeclaringClass();
if (!field.isStatic()) {
if (obj == null) {
throwNewNullPointerException();
}
RVMType objType = ObjectModel.getObjectType(obj);
if (objType != declaringClass && !RuntimeEntrypoints.isAssignableWith(declaringClass, objType)) {
throwNewIllegalArgumentException();
}
}
if (!field.isPublic() && !jlrField.isAccessible()) {
checkAccess(field, accessingClass);
}
if (field.isFinal() && (!jlrField.isAccessible() || field.isStatic()))
throwNewIllegalAccessException();
if (field.isStatic() && !declaringClass.isInitialized()) {
runClassInitializer(declaringClass);
}
}
/**
* Read a field from an object
* @param object to read from
* @param field to be read
* @param jlrField API version of field
* @param accessingClass class performing access
* @return the field's value
* @throws IllegalAccessException
* @throws IllegalArgumentException
*/
@Inline(value = Inline.When.ArgumentsAreConstant, arguments = {1})
static Object get(Object object, RVMField field, Field jlrField, RVMClass accessingClass) throws IllegalAccessException, IllegalArgumentException {
checkReadAccess(object, field, jlrField, accessingClass);
if (field.isReferenceType()) {
return field.getObjectValueUnchecked(object);
}
TypeReference type = field.getType();
if (type.isIntType()) {
return field.getIntValueUnchecked(object);
} else if (type.isCharType()) {
return field.getCharValueUnchecked(object);
} else if (type.isShortType()) {
return field.getShortValueUnchecked(object);
} else if (type.isLongType()) {
return field.getLongValueUnchecked(object);
} else if (type.isByteType()) {
return field.getByteValueUnchecked(object);
} else if (type.isBooleanType()) {
return field.getBooleanValueUnchecked(object);
} else if (type.isDoubleType()) {
return field.getDoubleValueUnchecked(object);
} else {
if (VM.VerifyAssertions) VM._assert(type.isFloatType());
return field.getFloatValueUnchecked(object);
}
}
@Inline(value = Inline.When.ArgumentsAreConstant, arguments = {1})
static boolean getBoolean(Object object, RVMField field, Field jlrField, RVMClass accessingClass) throws IllegalAccessException, IllegalArgumentException {
checkReadAccess(object, field, jlrField, accessingClass);
TypeReference type = field.getType();
if (!type.isBooleanType()) throwNewIllegalArgumentException("field type mismatch");
return field.getBooleanValueUnchecked(object);
}
@Inline(value = Inline.When.ArgumentsAreConstant, arguments = {1})
static byte getByte(Object object, RVMField field, Field jlrField, RVMClass accessingClass) throws IllegalAccessException, IllegalArgumentException {
checkReadAccess(object, field, jlrField, accessingClass);
TypeReference type = field.getType();
if (!type.isByteType()) throwNewIllegalArgumentException("field type mismatch");
return field.getByteValueUnchecked(object);
}
@Inline(value = Inline.When.ArgumentsAreConstant, arguments = {1})
static char getChar(Object object, RVMField field, Field jlrField, RVMClass accessingClass) throws IllegalAccessException, IllegalArgumentException {
checkReadAccess(object, field, jlrField, accessingClass);
TypeReference type = field.getType();
if (!type.isCharType()) throwNewIllegalArgumentException("field type mismatch");
return field.getCharValueUnchecked(object);
}
@Inline(value = Inline.When.ArgumentsAreConstant, arguments = {1})
static double getDouble(Object object, RVMField field, Field jlrField, RVMClass accessingClass) throws IllegalAccessException, IllegalArgumentException {
checkReadAccess(object, field, jlrField, accessingClass);
TypeReference type = field.getType();
if (type.isDoubleType()) {
return field.getDoubleValueUnchecked(object);
} else if (type.isFloatType()) {
return field.getFloatValueUnchecked(object);
} else if (type.isLongType()) {
return field.getLongValueUnchecked(object);
} else if (type.isIntType()) {
return field.getIntValueUnchecked(object);
} else if (type.isShortType()) {
return field.getShortValueUnchecked(object);
} else if (type.isCharType()) {
return field.getCharValueUnchecked(object);
} else if (type.isByteType()) {
return field.getByteValueUnchecked(object);
} else {
throwNewIllegalArgumentException("field type mismatch");
return 0.0d;
}
}
@Inline(value = Inline.When.ArgumentsAreConstant, arguments = {1})
static float getFloat(Object object, RVMField field, Field jlrField, RVMClass accessingClass) throws IllegalAccessException, IllegalArgumentException {
checkReadAccess(object, field, jlrField, accessingClass);
TypeReference type = field.getType();
if (type.isFloatType()) {
return field.getFloatValueUnchecked(object);
} else if (type.isLongType()) {
return field.getLongValueUnchecked(object);
} else if (type.isIntType()) {
return field.getIntValueUnchecked(object);
} else if (type.isShortType()) {
return field.getShortValueUnchecked(object);
} else if (type.isCharType()) {
return field.getCharValueUnchecked(object);
} else if (type.isByteType()) {
return field.getByteValueUnchecked(object);
} else {
throwNewIllegalArgumentException("field type mismatch");
return 0.0f;
}
}
@Inline(value = Inline.When.ArgumentsAreConstant, arguments = {1})
static int getInt(Object object, RVMField field, Field jlrField, RVMClass accessingClass) throws IllegalAccessException, IllegalArgumentException {
checkReadAccess(object, field, jlrField, accessingClass);
TypeReference type = field.getType();
if (type.isIntType()) {
return field.getIntValueUnchecked(object);
} else if (type.isShortType()) {
return field.getShortValueUnchecked(object);
} else if (type.isCharType()) {
return field.getCharValueUnchecked(object);
} else if (type.isByteType()) {
return field.getByteValueUnchecked(object);
} else {
throwNewIllegalArgumentException("field type mismatch");
return 0;
}
}
@Inline(value = Inline.When.ArgumentsAreConstant, arguments = {1})
static long getLong(Object object, RVMField field, Field jlrField, RVMClass accessingClass) throws IllegalAccessException, IllegalArgumentException {
checkReadAccess(object, field, jlrField, accessingClass);
TypeReference type = field.getType();
if (type.isLongType()) {
return field.getLongValueUnchecked(object);
} else if (type.isIntType()) {
return field.getIntValueUnchecked(object);
} else if (type.isShortType()) {
return field.getShortValueUnchecked(object);
} else if (type.isCharType()) {
return field.getCharValueUnchecked(object);
} else if (type.isByteType()) {
return field.getByteValueUnchecked(object);
} else {
throwNewIllegalArgumentException("field type mismatch");
return 0L;
}
}
@Inline(value = Inline.When.ArgumentsAreConstant, arguments = {1})
static short getShort(Object object, RVMField field, Field jlrField, RVMClass accessingClass) throws IllegalAccessException, IllegalArgumentException {
checkReadAccess(object, field, jlrField, accessingClass);
TypeReference type = field.getType();
if (type.isShortType()) {
return field.getShortValueUnchecked(object);
} else if (type.isByteType()) {
return field.getByteValueUnchecked(object);
} else {
throwNewIllegalArgumentException("field type mismatch");
return 0;
}
}
@Inline(value = Inline.When.ArgumentsAreConstant, arguments = {2})
static void set(Object object, Object value, RVMField field, Field jlrField, RVMClass accessingClass)
throws IllegalAccessException, IllegalArgumentException {
checkWriteAccess(object, field, jlrField, accessingClass);
if (field.isReferenceType()) {
if (value != null) {
RVMType valueType = ObjectModel.getObjectType(value);
RVMType fieldType = null;
try {
fieldType = field.getType().resolve();
} catch (NoClassDefFoundError e) {
throwNewIllegalArgumentException("field type mismatch");
}
if (fieldType != valueType &&
!RuntimeEntrypoints.isAssignableWith(fieldType, valueType)) {
throwNewIllegalArgumentException("field type mismatch");
}
}
field.setObjectValueUnchecked(object, value);
} else if (value instanceof Character) {
setCharInternal(object, (Character) value, field);
} else if (value instanceof Double) {
setDoubleInternal(object, (Double) value, field);
} else if (value instanceof Float) {
setFloatInternal(object, (Float) value, field);
} else if (value instanceof Long) {
setLongInternal(object, (Long) value, field);
} else if (value instanceof Integer) {
setIntInternal(object, (Integer) value, field);
} else if (value instanceof Short) {
setShortInternal(object, (Short) value, field);
} else if (value instanceof Byte) {
setByteInternal(object, (Byte) value, field);
} else if (value instanceof Boolean) {
setBooleanInternal(object, (Boolean) value, field);
} else {
throw new IllegalArgumentException("field type mismatch");
}
}
@Inline(value = Inline.When.ArgumentsAreConstant, arguments = {2})
static void setBoolean(Object object, boolean value, RVMField field, Field jlrField, RVMClass accessingClass)
throws IllegalAccessException, IllegalArgumentException {
checkWriteAccess(object, field, jlrField, accessingClass);
setBooleanInternal(object, value, field);
}
@Inline(value = Inline.When.ArgumentsAreConstant, arguments = {2})
static void setByte(Object object, byte value, RVMField field, Field jlrField, RVMClass accessingClass)
throws IllegalAccessException, IllegalArgumentException {
checkWriteAccess(object, field, jlrField, accessingClass);
setByteInternal(object, value, field);
}
@Inline(value = Inline.When.ArgumentsAreConstant, arguments = {2})
static void setChar(Object object, char value, RVMField field, Field jlrField, RVMClass accessingClass)
throws IllegalAccessException, IllegalArgumentException {
checkWriteAccess(object, field, jlrField, accessingClass);
setCharInternal(object, value, field);
}
@Inline(value = Inline.When.ArgumentsAreConstant, arguments = {2})
static void setDouble(Object object, double value, RVMField field, Field jlrField, RVMClass accessingClass)
throws IllegalAccessException, IllegalArgumentException {
checkWriteAccess(object, field, jlrField, accessingClass);
setDoubleInternal(object, value, field);
}
@Inline(value = Inline.When.ArgumentsAreConstant, arguments = {2})
static void setFloat(Object object, float value, RVMField field, Field jlrField, RVMClass accessingClass)
throws IllegalAccessException, IllegalArgumentException {
checkWriteAccess(object, field, jlrField, accessingClass);
setFloatInternal(object, value, field);
}
@Inline(value = Inline.When.ArgumentsAreConstant, arguments = {2})
static void setInt(Object object, int value, RVMField field, Field jlrField, RVMClass accessingClass)
throws IllegalAccessException, IllegalArgumentException {
checkWriteAccess(object, field, jlrField, accessingClass);
setIntInternal(object, value, field);
}
@Inline(value = Inline.When.ArgumentsAreConstant, arguments = {2})
static void setLong(Object object, long value, RVMField field, Field jlrField, RVMClass accessingClass)
throws IllegalAccessException, IllegalArgumentException {
checkWriteAccess(object, field, jlrField, accessingClass);
setLongInternal(object, value, field);
}
@Inline(value = Inline.When.ArgumentsAreConstant, arguments = {2})
static void setShort(Object object, short value, RVMField field, Field jlrField, RVMClass accessingClass)
throws IllegalAccessException, IllegalArgumentException {
checkWriteAccess(object, field, jlrField, accessingClass);
setShortInternal(object, value, field);
}
@Inline(value = Inline.When.ArgumentsAreConstant, arguments = {2})
private static void setBooleanInternal(Object object, boolean value, RVMField field)
throws IllegalArgumentException {
TypeReference type = field.getType();
if (type.isBooleanType())
field.setBooleanValueUnchecked(object, value);
else
throwNewIllegalArgumentException("field type mismatch");
}
@Inline(value = Inline.When.ArgumentsAreConstant, arguments = {2})
private static void setByteInternal(Object object, byte value, RVMField field) throws IllegalArgumentException {
TypeReference type = field.getType();
if (type.isByteType())
field.setByteValueUnchecked(object, value);
else if (type.isLongType())
field.setLongValueUnchecked(object, value);
else if (type.isIntType())
field.setIntValueUnchecked(object, value);
else if (type.isShortType())
field.setShortValueUnchecked(object, value);
else if (type.isCharType())
field.setCharValueUnchecked(object, (char)value);
else if (type.isDoubleType())
field.setDoubleValueUnchecked(object, value);
else if (type.isFloatType())
field.setFloatValueUnchecked(object, value);
else
throwNewIllegalArgumentException("field type mismatch");
}
@Inline(value = Inline.When.ArgumentsAreConstant, arguments = {2})
private static void setCharInternal(Object object, char value, RVMField field) throws IllegalArgumentException {
TypeReference type = field.getType();
if (type.isCharType())
field.setCharValueUnchecked(object, value);
else if (type.isLongType())
field.setLongValueUnchecked(object, value);
else if (type.isIntType())
field.setIntValueUnchecked(object, value);
else if (type.isShortType())
field.setShortValueUnchecked(object, (short)value);
else if (type.isDoubleType())
field.setDoubleValueUnchecked(object, value);
else if (type.isFloatType())
field.setFloatValueUnchecked(object, value);
else
throwNewIllegalArgumentException("field type mismatch");
}
@Inline(value = Inline.When.ArgumentsAreConstant, arguments = {2})
private static void setDoubleInternal(Object object, double value, RVMField field) throws IllegalArgumentException {
TypeReference type = field.getType();
if (type.isDoubleType())
field.setDoubleValueUnchecked(object, value);
else
throwNewIllegalArgumentException("field type mismatch");
}
@Inline(value = Inline.When.ArgumentsAreConstant, arguments = {2})
private static void setFloatInternal(Object object, float value, RVMField field) throws IllegalArgumentException {
TypeReference type = field.getType();
if (type.isFloatType())
field.setFloatValueUnchecked(object, value);
else if (type.isDoubleType())
field.setDoubleValueUnchecked(object, value);
else
throwNewIllegalArgumentException("field type mismatch");
}
@Inline(value = Inline.When.ArgumentsAreConstant, arguments = {2})
private static void setIntInternal(Object object, int value, RVMField field) throws IllegalArgumentException {
TypeReference type = field.getType();
if (type.isIntType())
field.setIntValueUnchecked(object, value);
else if (type.isLongType())
field.setLongValueUnchecked(object, value);
else if (type.isDoubleType())
field.setDoubleValueUnchecked(object, value);
else if (type.isFloatType())
field.setFloatValueUnchecked(object, value);
else
throwNewIllegalArgumentException("field type mismatch");
}
@Inline(value = Inline.When.ArgumentsAreConstant, arguments = {2})
private static void setLongInternal(Object object, long value, RVMField field) throws IllegalArgumentException {
TypeReference type = field.getType();
if (type.isLongType())
field.setLongValueUnchecked(object, value);
else if (type.isDoubleType())
field.setDoubleValueUnchecked(object, value);
else if (type.isFloatType())
field.setFloatValueUnchecked(object, value);
else
throwNewIllegalArgumentException("field type mismatch");
}
private static void setShortInternal(Object object, short value, RVMField field) throws IllegalArgumentException {
TypeReference type = field.getType();
if (type.isShortType())
field.setShortValueUnchecked(object, value);
else if (type.isLongType())
field.setLongValueUnchecked(object, value);
else if (type.isIntType())
field.setIntValueUnchecked(object, value);
else if (type.isDoubleType())
field.setDoubleValueUnchecked(object, value);
else if (type.isFloatType())
field.setFloatValueUnchecked(object, value);
else
throwNewIllegalArgumentException("field type mismatch");
}
}