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    }