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.ia32; 014 015import static org.jikesrvm.ia32.ArchConstants.SSE2_FULL; 016import static org.jikesrvm.ia32.RegisterConstants.NUM_PARAMETER_FPRS; 017import static org.jikesrvm.ia32.RegisterConstants.NUM_PARAMETER_GPRS; 018import static org.jikesrvm.runtime.Reflection.REFLECTION_FPRS_BITS; 019import static org.jikesrvm.runtime.Reflection.REFLECTION_GPRS_BITS; 020 021import org.jikesrvm.VM; 022import org.jikesrvm.classloader.RVMMethod; 023import org.jikesrvm.classloader.TypeReference; 024import org.jikesrvm.runtime.Magic; 025import org.vmmagic.pragma.UnpreemptibleNoWarn; 026import org.vmmagic.unboxed.Word; 027import org.vmmagic.unboxed.WordArray; 028 029/** 030 * Machine dependent portion of Reflective method invoker. 031 */ 032public abstract class MachineReflection { 033 034 /** 035 * Determines number/type of registers and parameters required to 036 * call specified method. 037 * Unlike the PowerPC code we count all the parameters, not just the 038 * ones that spill. This allow us to make enough space on the stack 039 * following the calling convention. 040 * 041 * @param method the method whose parameters to count 042 * @return number of parameters, gprs and frps encoded in a triple 043 */ 044 public static int countParameters(RVMMethod method) { 045 int GPRs = 0; 046 int FPRs = 0; 047 int parameters = 0; // parameters size in 32-bits quant. 048 049 int gp = NUM_PARAMETER_GPRS; // 0, 1, 2 050 int fp = NUM_PARAMETER_FPRS; // 0-8 051 052 if (!method.isStatic()) { 053 if (gp > 0) { 054 GPRs++; 055 gp--; 056 } 057 parameters++; 058 } 059 060 for (TypeReference t : method.getParameterTypes()) { 061 if (t.isLongType()) { 062 if (gp > 0) { 063 GPRs++; 064 gp--; 065 if (VM.BuildFor32Addr && gp > 0) { 066 GPRs++; 067 gp--; 068 } 069 } 070 parameters += 2; 071 } else if (t.isFloatType()) { 072 if (fp > 0) { 073 FPRs++; 074 fp--; 075 } 076 parameters++; 077 } else if (t.isDoubleType()) { 078 if (fp > 0) { 079 FPRs++; 080 fp--; 081 } 082 parameters += 2; 083 } else { // t is object, int, short, char, byte, or boolean 084 if (gp > 0) { 085 GPRs++; 086 gp--; 087 } 088 parameters++; 089 } 090 } 091 092 // hack to return triple 093 return (parameters << (REFLECTION_FPRS_BITS + REFLECTION_GPRS_BITS)) | 094 (FPRs << REFLECTION_GPRS_BITS) | 095 GPRs; 096 } 097 098 /** 099 * Collects parameters into arrays of registers/spills, as required to 100 * call specified method. 101 * 102 * @param method method whose parameters are to be packaged 103 * @param thisArg the receiver argument 104 * @param otherArgs all other arguments (primitives are boxed) 105 * @param GPRs space for GPRs (empty array if none needed) 106 * @param FPRs space for FPRs (empty array if none needed) 107 * @param FPRmeta meta-data for FPRs ({@code null} if no SSE2) 108 * @param Parameters more space for parameters. Refer to the source code 109 * to get all the details. 110 * 111 * @see #countParameters(RVMMethod) more machine-specific details 112 */ 113 @UnpreemptibleNoWarn("GC is disabled as Objects are turned into Words." + 114 "avoid preemption but still allow calls to preemptible unboxing routines") 115 public static void packageParameters(RVMMethod method, Object thisArg, Object[] otherArgs, WordArray GPRs, 116 double[] FPRs, byte[] FPRmeta, WordArray Parameters) { 117 int GPR = 0; 118 int FPR = SSE2_FULL ? 0 : FPRs.length; 119 int parameter = 0; 120 121 int gp = NUM_PARAMETER_GPRS; // 0, 1, 2 122 int fp = NUM_PARAMETER_FPRS; // 0-8 123 124 if (!method.isStatic()) { 125 Word val = Magic.objectAsAddress(thisArg).toWord(); 126 if (gp > 0) { 127 gp--; 128 GPRs.set(GPR++, val); 129 } 130 Parameters.set(parameter++, val); 131 } 132 133 TypeReference[] types = method.getParameterTypes(); 134 for (int i = 0; i < types.length; i++) { 135 TypeReference t = types[i]; 136 137 if (!t.isPrimitiveType()) { 138 Word val = Magic.objectAsAddress(otherArgs[i]).toWord(); 139 if (gp > 0) { 140 gp--; 141 GPRs.set(GPR++, val); 142 } 143 Parameters.set(parameter++, val); 144 } else if (t.isLongType()) { 145 long l = (Long)otherArgs[i]; 146 if (VM.BuildFor32Addr) { 147 if (gp > 0) { 148 gp--; 149 GPRs.set(GPR++, Word.fromIntZeroExtend((int) (l >>> 32))); 150 if (gp > 0) { 151 gp--; 152 GPRs.set(GPR++, Word.fromIntZeroExtend((int) (l))); 153 } 154 } 155 Parameters.set(parameter++, Word.fromIntZeroExtend((int) (l >>> 32))); 156 Parameters.set(parameter++, Word.fromIntZeroExtend((int) l)); 157 } else { 158 Word val = Word.fromLong(l); 159 if (gp > 0) { 160 gp--; 161 GPRs.set(GPR++, val); 162 } 163 Parameters.set(parameter++, val); 164 Parameters.set(parameter++, val); 165 } 166 } else if (t.isFloatType()) { 167 if (fp > 0) { 168 fp--; 169 if (SSE2_FULL) { 170 FPRs[FPR] = (Float)otherArgs[i]; 171 FPRmeta[FPR] = 0x0; 172 FPR++; 173 } else { 174 FPRs[--FPR] = (Float)otherArgs[i]; 175 } 176 } 177 float f = (Float)otherArgs[i]; 178 Parameters.set(parameter++, Word.fromIntZeroExtend(Float.floatToIntBits(f))); 179 } else if (t.isDoubleType()) { 180 if (VM.BuildFor32Addr) { 181 if (fp > 0) { 182 fp--; 183 if (SSE2_FULL) { 184 FPRs[FPR] = (Double)otherArgs[i]; 185 FPRmeta[FPR] = 0x1; 186 FPR++; 187 } else { 188 FPRs[--FPR] = (Double)otherArgs[i]; 189 } 190 } 191 double d = (Double)otherArgs[i]; 192 long l = Double.doubleToLongBits(d); 193 Parameters.set(parameter++, Word.fromIntZeroExtend((int) (l >>> 32))); 194 Parameters.set(parameter++, Word.fromIntZeroExtend((int) l)); 195 } else { 196 if (fp > 0) { 197 fp--; 198 if (SSE2_FULL) { 199 FPRs[FPR] = (Double)otherArgs[i]; 200 FPRmeta[FPR] = 0x1; 201 FPR++; 202 } else { 203 FPRs[--FPR] = (Double)otherArgs[i]; 204 } 205 } 206 double d = (Double)otherArgs[i]; 207 long l = Double.doubleToLongBits(d); 208 Word val = Word.fromLong(l); 209 Parameters.set(parameter++, val); 210 Parameters.set(parameter++, val); 211 } 212 } else if (t.isBooleanType()) { 213 boolean b = (Boolean)otherArgs[i]; 214 Word val = Word.fromIntZeroExtend(b ? 1 : 0); 215 if (gp > 0) { 216 gp--; 217 GPRs.set(GPR++, val); 218 } 219 Parameters.set(parameter++, val); 220 } else if (t.isCharType()) { 221 char c = (Character)otherArgs[i]; 222 Word val = Word.fromIntZeroExtend(c); 223 if (gp > 0) { 224 gp--; 225 GPRs.set(GPR++, val); 226 } 227 Parameters.set(parameter++, val); 228 } else { 229 if (VM.VerifyAssertions) VM._assert(t.isByteType() || t.isShortType() || t.isIntType()); 230 int x = ((Number)otherArgs[i]).intValue(); 231 Word val = Word.fromIntZeroExtend(x); 232 if (gp > 0) { 233 gp--; 234 GPRs.set(GPR++, val); 235 } 236 Parameters.set(parameter++, val); 237 } 238 } 239 } 240}