/* * 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.cellspu; import java.io.DataOutputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; import org.jikesrvm.SubordinateArchitecture; import org.jikesrvm.VM; import org.jikesrvm.runtime.VM_Magic; import org.jikesrvm.runtime.VM_Memory; /* * A block of machine code in the running virtual machine image. * * Machine code is an array of "instructions", declared formally as integers, * produced by VM_Compiler, typically by translating the bytecodes * of a VM_Method. The code entrypoint is the first word in the array. */ public abstract class VM_MachineCode extends org.jikesrvm.VM_MachineCode { /** * Get the instructions comprising this block of machine code. */ public SubordinateArchitecture.VM_CodeArray getInstructions() { if (VM.VerifyAssertions) VM._assert(instructions != null); // must call "finish" first return instructions; } /** * Get the bytecode-to-instruction map for this block of machine code. * @return an array co-indexed with bytecode array. Each entry is an offset * into the array of machine codes giving the first instruction that the * bytecode compiled to. * @see #getInstructions */ public int[] getBytecodeMap() { return bytecode_2_machine; } /** * Finish generation of assembler code. */ public void finish() { if (VM.VerifyAssertions) VM._assert(instructions == null); // finish must only be called once /* NOTE: MM_Interface.pickAllocator() depends on the name of this class and method to identify code allocation */ int n = (next_bundle - 1) * size + next; instructions = SubordinateArchitecture.VM_CodeArray.Factory.create(n, false); int k = 0; for (int i = 0; i < next_bundle; i++) { int[] b = bundles.get(i); int m = (i == next_bundle - 1 ? next : size); for (int j = 0; j < m; j++) { instructions.set(k++, b[j]); } } // synchronize icache with generated machine code that was written through dcache // if (VM.runningVM) { VM_Memory.sync(VM_Magic.objectAsAddress(instructions), instructions.length() << VM_RegisterConstants.LG_INSTRUCTION_WIDTH); } // release work buffers // bundles = null; current_bundle = null; } public void addInstruction(int instr) { if (next < current_bundle.length) { current_bundle[next++] = instr; } else { current_bundle = new int[size]; bundles.add(current_bundle); next_bundle++; next = 0; current_bundle[next++] = instr; } } public int getInstruction(int k) { int i = k >> shift; int j = k & mask; int[] b = bundles.get(i); return b[j]; } public void putInstruction(int k, int instr) { int i = k >> shift; int j = k & mask; int[] b = bundles.get(i); b[j] = instr; } public void setBytecodeMap(int[] b2m) { bytecode_2_machine = b2m; } public void dumpInstructions(File outFile) { try { DataOutputStream out = new DataOutputStream(new FileOutputStream (outFile)); int n = (next_bundle - 1) * size + next; int k = 0; for (int i = 0; i < next_bundle; i++) { int[] b = bundles.get(i); int m = (i == next_bundle - 1 ? next : size); for (int j = 0; j < m; j++) { out.writeInt(b[j]); } } } catch (IOException e) { if (e instanceof FileNotFoundException) { System.out.println("Cannot find file " + outFile.getName() + " for dump of codeArray.\n"); } else { System.out.println("IOException when dumping code Array.\n" + e); } } } private int[] bytecode_2_machine; // See setBytecodeMap/getBytecodeMap /* Unfortunately, the number of instructions is not known in advance. This class implements a vector of instructions (ints). It uses a vector -- bundles -- whose elements are each int[size] arrays of instructions. size is assumed to be a power of two. */ private static final int mask = 0xFF; private static final int size = mask + 1; private static final int shift = 8; private SubordinateArchitecture.VM_CodeArray instructions; private ArrayList<int[]> bundles; private int[] current_bundle; private int next; private int next_bundle; public VM_MachineCode() { bundles = new ArrayList<int[]>(); current_bundle = new int[size]; bundles.add(current_bundle); next_bundle++; } }