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