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}