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