/* * 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 org.jikesrvm.VM; import org.jikesrvm.Constants; 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 implements RegisterConstants { /** * Determine 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. */ 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 << (Constants.REFLECTION_FPRS_BITS + Constants.REFLECTION_GPRS_BITS)) | (FPRs << Constants.REFLECTION_GPRS_BITS) | GPRs; } /** * Collect parameters into arrays of registers/spills, as required to * call specified method. */ @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 = ArchConstants.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 (ArchConstants.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 (ArchConstants.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 (ArchConstants.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); } } } }