/* * 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 org.jikesrvm.ia32; import static org.jikesrvm.ia32.ArchConstants.SSE2_FULL; import static org.jikesrvm.ia32.RegisterConstants.NUM_PARAMETER_FPRS; import static org.jikesrvm.ia32.RegisterConstants.NUM_PARAMETER_GPRS; import static org.jikesrvm.runtime.Reflection.REFLECTION_FPRS_BITS; import static org.jikesrvm.runtime.Reflection.REFLECTION_GPRS_BITS; import org.jikesrvm.VM; import org.jikesrvm.classloader.RVMMethod; import org.jikesrvm.classloader.TypeReference; import org.jikesrvm.runtime.Magic; import org.vmmagic.pragma.UnpreemptibleNoWarn; import org.vmmagic.unboxed.Word; import org.vmmagic.unboxed.WordArray; /** * Machine dependent portion of Reflective method invoker. */ public abstract class MachineReflection { /** * Determines number/type of registers and parameters required to * call specified method. * Unlike the PowerPC code we count all the parameters, not just the * ones that spill. This allow us to make enough space on the stack * following the calling convention. * * @param method the method whose parameters to count * @return number of parameters, gprs and frps encoded in a triple */ public static int countParameters(RVMMethod method) { int GPRs = 0; int FPRs = 0; int parameters = 0; // parameters size in 32-bits quant. int gp = NUM_PARAMETER_GPRS; // 0, 1, 2 int fp = NUM_PARAMETER_FPRS; // 0-8 if (!method.isStatic()) { if (gp > 0) { GPRs++; gp--; } parameters++; } for (TypeReference t : method.getParameterTypes()) { if (t.isLongType()) { if (gp > 0) { GPRs++; gp--; if (VM.BuildFor32Addr && gp > 0) { GPRs++; gp--; } } parameters += 2; } else if (t.isFloatType()) { if (fp > 0) { FPRs++; fp--; } parameters++; } else if (t.isDoubleType()) { if (fp > 0) { FPRs++; fp--; } parameters += 2; } else { // t is object, int, short, char, byte, or boolean if (gp > 0) { GPRs++; gp--; } parameters++; } } // hack to return triple return (parameters << (REFLECTION_FPRS_BITS + REFLECTION_GPRS_BITS)) | (FPRs << REFLECTION_GPRS_BITS) | GPRs; } /** * Collects parameters into arrays of registers/spills, as required to * call specified method. * * @param method method whose parameters are to be packaged * @param thisArg the receiver argument * @param otherArgs all other arguments (primitives are boxed) * @param GPRs space for GPRs (empty array if none needed) * @param FPRs space for FPRs (empty array if none needed) * @param FPRmeta meta-data for FPRs ({@code null} if no SSE2) * @param Parameters more space for parameters. Refer to the source code * to get all the details. * * @see #countParameters(RVMMethod) more machine-specific details */ @UnpreemptibleNoWarn("GC is disabled as Objects are turned into Words." + "avoid preemption but still allow calls to preemptible unboxing routines") public static void packageParameters(RVMMethod method, Object thisArg, Object[] otherArgs, WordArray GPRs, double[] FPRs, byte[] FPRmeta, WordArray Parameters) { int GPR = 0; int FPR = SSE2_FULL ? 0 : FPRs.length; int parameter = 0; int gp = NUM_PARAMETER_GPRS; // 0, 1, 2 int fp = NUM_PARAMETER_FPRS; // 0-8 if (!method.isStatic()) { Word val = Magic.objectAsAddress(thisArg).toWord(); if (gp > 0) { gp--; GPRs.set(GPR++, val); } Parameters.set(parameter++, val); } TypeReference[] types = method.getParameterTypes(); for (int i = 0; i < types.length; i++) { TypeReference t = types[i]; if (!t.isPrimitiveType()) { Word val = Magic.objectAsAddress(otherArgs[i]).toWord(); if (gp > 0) { gp--; GPRs.set(GPR++, val); } Parameters.set(parameter++, val); } else if (t.isLongType()) { long l = (Long)otherArgs[i]; if (VM.BuildFor32Addr) { if (gp > 0) { gp--; GPRs.set(GPR++, Word.fromIntZeroExtend((int) (l >>> 32))); if (gp > 0) { gp--; GPRs.set(GPR++, Word.fromIntZeroExtend((int) (l))); } } Parameters.set(parameter++, Word.fromIntZeroExtend((int) (l >>> 32))); Parameters.set(parameter++, Word.fromIntZeroExtend((int) l)); } else { Word val = Word.fromLong(l); if (gp > 0) { gp--; GPRs.set(GPR++, val); } Parameters.set(parameter++, val); Parameters.set(parameter++, val); } } else if (t.isFloatType()) { if (fp > 0) { fp--; if (SSE2_FULL) { FPRs[FPR] = (Float)otherArgs[i]; FPRmeta[FPR] = 0x0; FPR++; } else { FPRs[--FPR] = (Float)otherArgs[i]; } } float f = (Float)otherArgs[i]; Parameters.set(parameter++, Word.fromIntZeroExtend(Float.floatToIntBits(f))); } else if (t.isDoubleType()) { if (VM.BuildFor32Addr) { if (fp > 0) { fp--; if (SSE2_FULL) { FPRs[FPR] = (Double)otherArgs[i]; FPRmeta[FPR] = 0x1; FPR++; } else { FPRs[--FPR] = (Double)otherArgs[i]; } } double d = (Double)otherArgs[i]; long l = Double.doubleToLongBits(d); Parameters.set(parameter++, Word.fromIntZeroExtend((int) (l >>> 32))); Parameters.set(parameter++, Word.fromIntZeroExtend((int) l)); } else { if (fp > 0) { fp--; if (SSE2_FULL) { FPRs[FPR] = (Double)otherArgs[i]; FPRmeta[FPR] = 0x1; FPR++; } else { FPRs[--FPR] = (Double)otherArgs[i]; } } double d = (Double)otherArgs[i]; long l = Double.doubleToLongBits(d); Word val = Word.fromLong(l); Parameters.set(parameter++, val); Parameters.set(parameter++, val); } } else if (t.isBooleanType()) { boolean b = (Boolean)otherArgs[i]; Word val = Word.fromIntZeroExtend(b ? 1 : 0); if (gp > 0) { gp--; GPRs.set(GPR++, val); } Parameters.set(parameter++, val); } else if (t.isCharType()) { char c = (Character)otherArgs[i]; Word val = Word.fromIntZeroExtend(c); if (gp > 0) { gp--; GPRs.set(GPR++, val); } Parameters.set(parameter++, val); } else { if (VM.VerifyAssertions) VM._assert(t.isByteType() || t.isShortType() || t.isIntType()); int x = ((Number)otherArgs[i]).intValue(); Word val = Word.fromIntZeroExtend(x); if (gp > 0) { gp--; GPRs.set(GPR++, val); } Parameters.set(parameter++, val); } } } }