/* * This file is part of the Jikes RVM project (http://jikesrvm.org). * * This file is licensed to You under the Eclipse Public License (EPL); * 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/eclipse-1.0.php * * See the COPYRIGHT.txt file distributed with this work for information * regarding copyright ownership. */ package org.jikesrvm.compilers.opt.instrsched; import org.jikesrvm.compilers.opt.ir.Instruction; /** * Resource usage map representation * Used by the scheduler to accomodate resource patterns * * @see OperatorClass * @see org.jikesrvm.compilers.opt.ir.Operator */ final class ResourceMap { private static final int VERBOSE = 0; private static void debug(String s) { System.out.println(s); } private static String toBinaryPad32(int value) { String s = Integer.toBinaryString(value); return String.format("%032s", 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] = OperatorClass.NONE; } rumap = t; } size = s; } /** * Creates new resource map. */ public ResourceMap() { this(4); } /** * Creates new resource map with desired initial length. * * @param length desired initial length of the resource map */ public ResourceMap(int length) { rumap = new int[length]; size = 0; for (int i = 0; i < length; i++) { rumap[i] = 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(Instruction) */ public boolean schedule(Instruction i, int time) { if (SchedulingInfo.isScheduled(i)) { throw new InternalError("Already scheduled"); } 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)) { SchedulingInfo.setInfo(i, alt, time); return true; } } return false; } /** * Frees resources for given instruction. * * @param i instruction * @see #schedule(Instruction,int) */ public void unschedule(Instruction i) { if (!SchedulingInfo.isScheduled(i)) { throw new InternalError("Not scheduled"); } OperatorClass opc = i.operator().getOpClass(); int[] ru = opc.masks[SchedulingInfo.getAlt(i)]; unschedule(ru, SchedulingInfo.getTime(i)); 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]; } } }