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 }