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.compilers.opt.runtimesupport;
014
015 import org.jikesrvm.VM;
016 import org.jikesrvm.classloader.RVMArray;
017 import org.jikesrvm.classloader.BytecodeConstants;
018 import org.jikesrvm.classloader.BytecodeStream;
019 import org.jikesrvm.classloader.NormalMethod;
020 import org.jikesrvm.classloader.TableBasedDynamicLinker;
021 import org.jikesrvm.classloader.TypeReference;
022 import org.jikesrvm.runtime.RuntimeEntrypoints;
023 import org.vmmagic.unboxed.Offset;
024
025 /**
026 * Routines for dynamic linking and other misc hooks from opt-compiled code to
027 * runtime services.
028 *
029 * @see org.jikesrvm.ArchitectureSpecificOpt.FinalMIRExpansion
030 * @see OptSaveVolatile (transitions from compiled code to resolveDynamicLink)
031 * @see TableBasedDynamicLinker
032 */
033 public final class OptLinker implements BytecodeConstants {
034
035 /**
036 * Given an opt compiler info and a machine code offset in that method's
037 * instruction array, perform the dynamic linking required by that
038 * instruction.
039 * <p>
040 * We do this by mapping back to the source RVMMethod and bytecode offset,
041 * then examining the bytecodes to see what field/method was being
042 * referenced, then calling TableBasedDynamicLinker to do the real work.
043 */
044 public static void resolveDynamicLink(OptCompiledMethod cm, Offset offset) throws NoClassDefFoundError {
045 OptMachineCodeMap map = cm.getMCMap();
046 int bci = map.getBytecodeIndexForMCOffset(offset);
047 NormalMethod realMethod = map.getMethodForMCOffset(offset);
048 if (bci == -1 || realMethod == null) {
049 VM.sysFail("Mapping to source code location not available at Dynamic Linking point\n");
050 }
051 BytecodeStream bcodes = realMethod.getBytecodes();
052 bcodes.reset(bci);
053 int opcode = bcodes.nextInstruction();
054 switch (opcode) {
055 case JBC_getfield:
056 case JBC_putfield:
057 case JBC_getstatic:
058 case JBC_putstatic:
059 TableBasedDynamicLinker.resolveMember(bcodes.getFieldReference());
060 break;
061 case JBC_invokevirtual:
062 case JBC_invokestatic:
063 case JBC_invokespecial:
064 TableBasedDynamicLinker.resolveMember(bcodes.getMethodReference());
065 break;
066 case JBC_invokeinterface:
067 default:
068 if (VM.VerifyAssertions) {
069 VM._assert(VM.NOT_REACHED, "Unexpected case in OptLinker.resolveDynamicLink");
070 }
071 break;
072 }
073 }
074
075 /*
076 * Method referenced from Entrypoints
077 */
078 public static Object newArrayArray(int methodId, int[] dimensions, int typeId)
079 throws NoClassDefFoundError, NegativeArraySizeException, OutOfMemoryError {
080 // validate arguments
081 for (int dimension : dimensions) {
082 if (dimension < 0) throw new NegativeArraySizeException();
083 }
084 // create array
085 //
086 RVMArray aType = (RVMArray) TypeReference.getTypeRef(typeId).resolve();
087 return RuntimeEntrypoints.buildMultiDimensionalArray(methodId, dimensions, aType);
088 }
089
090 public static Object new2DArray(int methodId, int dim0, int dim1, int typeId)
091 throws NoClassDefFoundError, NegativeArraySizeException, OutOfMemoryError {
092 // validate arguments
093 if ((dim0 < 0)||(dim1 < 0)) throw new NegativeArraySizeException();
094
095 // create array
096 //
097 RVMArray aType = (RVMArray) TypeReference.getTypeRef(typeId).resolve();
098 return RuntimeEntrypoints.buildTwoDimensionalArray(methodId, dim0, dim1, aType);
099 }
100 }