/* * This file is part of the Jikes RVM project (http://jikesrvm.org). * * This file is licensed to You under the Common Public License (CPL); * 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/cpl1.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.VM_Constants; import org.jikesrvm.classloader.VM_Method; import org.jikesrvm.classloader.VM_TypeReference; import org.jikesrvm.runtime.VM_Reflection; import org.vmmagic.unboxed.Word; import org.vmmagic.unboxed.WordArray; /** * Machine dependent portion of Reflective method invoker. */ public abstract class VM_MachineReflection implements VM_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(VM_Method 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 (VM_TypeReference t : method.getParameterTypes()) { if (t.isLongType()) { if (gp > 0) { GPRs++; gp--; if (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 << (VM_Constants.REFLECTION_FPRS_BITS + VM_Constants.REFLECTION_GPRS_BITS)) | (FPRs << VM_Constants.REFLECTION_GPRS_BITS) | GPRs; } /** * Collect parameters into arrays of registers/spills, as required to * call specified method. */ public static void packageParameters(VM_Method method, Object thisArg, Object[] otherArgs, WordArray GPRs, double[] FPRs, byte[] FPRmeta, WordArray Parameters) { int GPR = 0; int FPR = VM_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 = VM_Reflection.unwrapObject(thisArg).toWord(); if (gp > 0) { gp--; GPRs.set(GPR++, val); } Parameters.set(parameter++, val); } VM_TypeReference[] types = method.getParameterTypes(); for (int i = 0; i < types.length; i++) { VM_TypeReference t = types[i]; if (t.isLongType()) { long l = VM_Reflection.unwrapLong(otherArgs[i]); 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 if (t.isFloatType()) { if (fp > 0) { fp--; if (VM_ArchConstants.SSE2_FULL) { FPRs[FPR] = VM_Reflection.unwrapFloat(otherArgs[i]); FPRmeta[FPR] = 0x0; FPR++; } else { FPRs[--FPR] = VM_Reflection.unwrapFloat(otherArgs[i]); } } float f = VM_Reflection.unwrapFloat(otherArgs[i]); Parameters.set(parameter++, Word.fromIntZeroExtend(Float.floatToIntBits(f))); } else if (t.isDoubleType()) { if (fp > 0) { fp--; if (VM_ArchConstants.SSE2_FULL) { FPRs[FPR] = VM_Reflection.unwrapDouble(otherArgs[i]); FPRmeta[FPR] = 0x1; FPR++; } else { FPRs[--FPR] = VM_Reflection.unwrapDouble(otherArgs[i]); } } double d = VM_Reflection.unwrapDouble(otherArgs[i]); long l = Double.doubleToLongBits(d); Parameters.set(parameter++, Word.fromIntZeroExtend((int) (l >>> 32))); Parameters.set(parameter++, Word.fromIntZeroExtend((int) l)); } else if (t.isBooleanType()) { Word val = Word.fromIntZeroExtend(VM_Reflection.unwrapBooleanAsInt(otherArgs[i])); if (gp > 0) { gp--; GPRs.set(GPR++, val); } Parameters.set(parameter++, val); } else if (t.isByteType()) { Word val = Word.fromIntZeroExtend(VM_Reflection.unwrapByte(otherArgs[i])); if (gp > 0) { gp--; GPRs.set(GPR++, val); } Parameters.set(parameter++, val); } else if (t.isCharType()) { Word val = Word.fromIntZeroExtend(VM_Reflection.unwrapChar(otherArgs[i])); if (gp > 0) { gp--; GPRs.set(GPR++, val); } Parameters.set(parameter++, val); } else if (t.isShortType()) { Word val = Word.fromIntZeroExtend(VM_Reflection.unwrapShort(otherArgs[i])); if (gp > 0) { gp--; GPRs.set(GPR++, val); } Parameters.set(parameter++, val); } else if (t.isIntType()) { Word val = Word.fromIntZeroExtend(VM_Reflection.unwrapInt(otherArgs[i])); if (gp > 0) { gp--; GPRs.set(GPR++, val); } Parameters.set(parameter++, val); } else if (!t.isPrimitiveType()) { Word val = VM_Reflection.unwrapObject(otherArgs[i]).toWord(); if (gp > 0) { gp--; GPRs.set(GPR++, val); } Parameters.set(parameter++, val); } else { if (VM.VerifyAssertions) VM._assert(VM_Constants.NOT_REACHED); } } } }