/* * 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.compilers.opt.ir.OPT_Instruction; /** * Resource usage map representation * Used by the scheduler to accomodate resource patterns * * @see OPT_OperatorClass * @see org.jikesrvm.compilers.opt.ir.OPT_Operator */ final class OPT_ResourceMap { private static final int verbose = 0; private static void debug(String s) { System.out.println(s); } // Padding // For internal use only. private static final String ZEROS = dup(32, '0'); private static String toBinaryPad32(int value) { String s = Integer.toBinaryString(value); return ZEROS.substring(s.length()) + s; } // GROWABLE Resource Usage map. private int[] rumap; // Current size of the RU map. private int size; // Grows the RU map to a given size. // For internal use only. private void grow(int s) { if (verbose >= 2) { debug("Growing from " + size + " to " + s); } if (size >= s) { return; } int len = rumap.length; if (len < s) { for (; len < s; len <<= 1) ; int[] t = new int[len]; for (int i = 0; i < rumap.length; i++) { t[i] = rumap[i]; } for (int i = rumap.length; i < len; i++) { t[i] = OPT_OperatorClass.NONE; } rumap = t; } size = s; } /** * Creates new resource map. */ public OPT_ResourceMap() { this(4); } /** * Creates new resource map with desired initial length. * * @param length desired initial length of the resource map */ public OPT_ResourceMap(int length) { rumap = new int[length]; size = 0; for (int i = 0; i < length; i++) { rumap[i] = OPT_OperatorClass.NONE; } } /** * Reserves resources for given instruction at given time. * * @param i instruction * @param time time to schedule * @return true if succeeded, false if there was a conflict * @see #unschedule(OPT_Instruction) */ public boolean schedule(OPT_Instruction i, int time) { if (OPT_SchedulingInfo.isScheduled(i)) { throw new InternalError("Already scheduled"); } OPT_OperatorClass opc = i.operator().getOpClass(); if (verbose >= 2) { debug("Op Class=" + opc); } for (int alt = 0; alt < opc.masks.length; alt++) { int[] ru = opc.masks[alt]; if (schedule(ru, time)) { OPT_SchedulingInfo.setInfo(i, alt, time); return true; } } return false; } /** * Frees resources for given instruction. * * @param i instruction * @see #schedule(OPT_Instruction,int) */ public void unschedule(OPT_Instruction i) { if (!OPT_SchedulingInfo.isScheduled(i)) { throw new InternalError("Not scheduled"); } OPT_OperatorClass opc = i.operator().getOpClass(); int[] ru = opc.masks[OPT_SchedulingInfo.getAlt(i)]; unschedule(ru, OPT_SchedulingInfo.getTime(i)); OPT_SchedulingInfo.resetInfo(i); } /** * Returns a string representation of the resource map. * * @return a string representation of the resource map */ public String toString() { StringBuilder sb = new StringBuilder(); for (int i = 0; i < size; i++) { sb.append(toBinaryPad32(rumap[i])).append("\n"); } return sb.toString(); } // Binds resources for given resource usage pattern at given time. // Returns false if there is a resource conflict. // For internal use only. private boolean schedule(int[] usage, int time) { grow(time + usage.length); if (verbose >= 1) { debug("Pattern (" + usage.length + ")"); for (int anUsage : usage) debug(" " + toBinaryPad32(anUsage)); debug(""); } for (int i = 0; i < usage.length; i++) { if ((usage[i] & rumap[time + i]) != 0) { return false; } } for (int i = 0; i < usage.length; i++) { rumap[time + i] |= usage[i]; } return true; } // Unbinds resources for given resource usage pattern at given time. // For internal use only. private void unschedule(int[] usage, int time) { for (int i = 0; i < usage.length; i++) { rumap[time + i] &= ~usage[i]; } } // Generates a string of a given length filled by a given character. // For internal use only. private static String dup(int len, char c) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < len; i++) { sb.append(c); } return sb.toString(); } }