/*
* This file is part of the Jikes RVM project (http://jikesrvm.org).
*
* This file is licensed to You under the Common Public License (CPL);
* You may not use this file except in compliance with the License. You
* may obtain a copy of the License at
*
* http://www.opensource.org/licenses/cpl1.0.php
*
* See the COPYRIGHT.txt file distributed with this work for information
* regarding copyright ownership.
*/
package org.jikesrvm.compilers.opt;
import org.jikesrvm.VM;
import org.jikesrvm.classloader.VM_Array;
import org.jikesrvm.classloader.VM_BytecodeConstants;
import org.jikesrvm.classloader.VM_BytecodeStream;
import org.jikesrvm.classloader.VM_NormalMethod;
import org.jikesrvm.classloader.VM_TableBasedDynamicLinker;
import org.jikesrvm.classloader.VM_TypeReference;
import org.jikesrvm.runtime.VM_Runtime;
import org.vmmagic.unboxed.Offset;
//TODO - Deal with Subarch
/**
* Routines for dynamic linking and other misc hooks from opt-compiled code to
* runtime services.
*
* @see org.jikesrvm.ArchitectureSpecific.OPT_FinalMIRExpansion
* @see VM_OptSaveVolatile (transitions from compiled code to resolveDynamicLink)
* @see VM_TableBasedDynamicLinker
*/
public final class VM_OptLinker implements VM_BytecodeConstants {
/**
* Given an opt compiler info and a machine code offset in that method's
* instruction array, perform the dynamic linking required by that
* instruction.
* <p>
* We do this by mapping back to the source VM_Method and bytecode offset,
* then examining the bytecodes to see what field/method was being
* referenced, then calling VM_TableBasedDynamicLinker to do the real work.
*/
public static void resolveDynamicLink(VM_OptCompiledMethod cm, Offset offset) throws NoClassDefFoundError {
VM_OptMachineCodeMap map = cm.getMCMap();
int bci = map.getBytecodeIndexForMCOffset(offset);
VM_NormalMethod realMethod = map.getMethodForMCOffset(offset);
if (bci == -1 || realMethod == null) {
VM.sysFail("Mapping to source code location not available at Dynamic Linking point\n");
}
VM_BytecodeStream bcodes = realMethod.getBytecodes();
bcodes.reset(bci);
int opcode = bcodes.nextInstruction();
switch (opcode) {
case JBC_getfield:
case JBC_putfield:
case JBC_getstatic:
case JBC_putstatic:
VM_TableBasedDynamicLinker.resolveMember(bcodes.getFieldReference(), false);
break;
case JBC_invokevirtual:
case JBC_invokestatic:
case JBC_invokespecial:
VM_TableBasedDynamicLinker.resolveMember(bcodes.getMethodReference(), false);
break;
case JBC_invokeinterface:
default:
if (VM.VerifyAssertions) {
VM._assert(VM.NOT_REACHED, "Unexpected case in VM_OptLinker.resolveDynamicLink");
}
break;
}
}
/*
* Method referenced from VM_Entrypoints
*/
public static Object newArrayArray(int methodId, int[] dimensions, int typeId)
throws NoClassDefFoundError, NegativeArraySizeException, OutOfMemoryError {
// validate arguments
for (int dimension : dimensions) {
if (dimension < 0) throw new NegativeArraySizeException();
}
// create array
//
VM_Array aType = (VM_Array) VM_TypeReference.getTypeRef(typeId).resolve(false);
return VM_Runtime.buildMultiDimensionalArray(methodId, dimensions, aType);
}
}