001/* 002 * This file is part of the Jikes RVM project (http://jikesrvm.org). 003 * 004 * This file is licensed to You under the Eclipse Public License (EPL); 005 * You may not use this file except in compliance with the License. You 006 * may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/eclipse-1.0.php 009 * 010 * See the COPYRIGHT.txt file distributed with this work for information 011 * regarding copyright ownership. 012 */ 013package org.jikesrvm.runtime; 014 015import org.jikesrvm.classloader.RVMMethod; 016import org.vmmagic.pragma.Inline; 017import org.vmmagic.pragma.NoInline; 018 019/** 020 * Base class for all reflective method invoker classes, contains utility 021 * methods that are invoked to unwrap the reflective arguments. Also contains 022 * {@link #invoke(RVMMethod, Object, Object[])} that is called to perform the reflective 023 * method call. 024 */ 025public abstract class ReflectionBase { 026 027 @NoInline 028 private static void throwIllegalArgumentException() throws IllegalArgumentException { 029 throw new IllegalArgumentException(); 030 } 031 032 @Inline 033 protected static boolean unboxAsBoolean(Object obj) { 034 if ((obj == null) || !(obj instanceof Boolean)) { 035 throwIllegalArgumentException(); 036 } 037 return ((Boolean)obj).booleanValue(); 038 } 039 040 @Inline 041 protected static Object boxAsBoolean(boolean b) { 042 return b; 043 } 044 045 @Inline 046 protected static byte unboxAsByte(Object obj) { 047 if ((obj == null) || !(obj instanceof Byte)) { 048 throwIllegalArgumentException(); 049 } 050 return ((Byte)obj).byteValue(); 051 } 052 053 @Inline 054 protected static Object boxAsByte(byte b) { 055 return b; 056 } 057 058 @Inline 059 protected static short unboxAsShort(Object obj) { 060 if ((obj == null) || (!(obj instanceof Short) && !(obj instanceof Byte))) { 061 throwIllegalArgumentException(); 062 } 063 return ((Number)obj).shortValue(); 064 } 065 066 @Inline 067 protected static Object boxAsShort(short s) { 068 return s; 069 } 070 071 @Inline 072 protected static char unboxAsChar(Object obj) { 073 if ((obj == null) || !(obj instanceof Character)) { 074 throwIllegalArgumentException(); 075 } 076 return ((Character)obj).charValue(); 077 } 078 079 @Inline 080 protected static Object boxAsChar(char c) { 081 return c; 082 } 083 084 @Inline 085 protected static int unboxAsInt(Object obj) { 086 if ((obj == null) || 087 (!(obj instanceof Integer) && !(obj instanceof Character) && 088 !(obj instanceof Short) && !(obj instanceof Byte))) { 089 throwIllegalArgumentException(); 090 } 091 return ((Number)obj).intValue(); 092 } 093 094 @Inline 095 protected static Object boxAsInt(int i) { 096 return i; 097 } 098 099 @Inline 100 protected static long unboxAsLong(Object obj) { 101 if ((obj == null) || 102 (!(obj instanceof Long) && !(obj instanceof Integer) && 103 !(obj instanceof Character) && !(obj instanceof Short) && 104 !(obj instanceof Byte))) { 105 throwIllegalArgumentException(); 106 } 107 return ((Number)obj).longValue(); 108 } 109 110 @Inline 111 protected static Object boxAsLong(long l) { 112 return l; 113 } 114 115 @Inline 116 protected static float unboxAsFloat(Object obj) { 117 if ((obj == null) || !(obj instanceof Float)) { 118 throwIllegalArgumentException(); 119 } 120 return ((Float)obj).floatValue(); 121 } 122 123 @Inline 124 protected static Object boxAsFloat(float f) { 125 return f; 126 } 127 128 @Inline 129 protected static double unboxAsDouble(Object obj) { 130 if ((obj == null) || 131 (!(obj instanceof Double) && !(obj instanceof Float))) { 132 throwIllegalArgumentException(); 133 } 134 return ((Number)obj).doubleValue(); 135 } 136 137 @Inline 138 protected static Object boxAsDouble(double d) { 139 return d; 140 } 141 142 /** 143 * Invoke reflective method being wrapped by this object, internal method 144 * specific part. 145 * @param obj object for virtual method invocation 146 * @param args arguments to method call 147 * @return the object that is the result of the invoke 148 */ 149 public abstract Object invokeInternal(Object obj, Object[] args); 150 151 /** 152 * Invoke reflective method being wrapped by this object 153 * @param method the method to invoke 154 * @param obj object for virtual method invocation 155 * @param args arguments to method call 156 * @return the object that is the result of the invoke 157 */ 158 public final Object invoke(RVMMethod method, Object obj, Object[] args) { 159 int argsLength = args == null ? 0 : args.length; 160 if (method.getParameterTypes().length != argsLength) { 161 throwIllegalArgumentException(); 162 } 163 try { 164 return invokeInternal(obj, args); 165 } catch (ClassCastException e) { 166 // FIXME: This is fragile and ill-advised way to handle this situation 167 // I think A more robust way to handle it would be to put in the appropriate 168 // try/catch structure in the generated bytecodes and handle it there. 169 if (e.getStackTrace().length == (new Throwable()).getStackTrace().length + 6) { 170 throw new IllegalArgumentException("argument type mismatch", e); 171 } else { 172 throw e; 173 } 174 } 175 } 176 177 /** 178 * Reflective method invoker that performs no invocation 179 */ 180 public static final ReflectionBase nullInvoker = new ReflectionBase() { 181 @Override 182 public Object invokeInternal(Object obj, Object[] args) { 183 return null; 184 } 185 }; 186}