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}