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 */
013package org.mmtk.vm.gcspy;
014
015import org.mmtk.utility.Log;
016import org.vmmagic.unboxed.*;
017import org.vmmagic.pragma.*;
018
019/**
020 * Abstract class that provides generally useful
021 * methods.
022 */
023@Uninterruptible public abstract class Util {
024
025  /**
026   * Allocate an array of bytes with malloc
027   *
028   * @param size The size to allocate
029   * @return The start address of the memory allocated in C space
030   * @see #free
031  */
032  public abstract Address malloc(int size);
033
034  /**
035   * Free an array of bytes previously allocated with malloc
036   *
037   * @param addr The address of some memory previously allocated with malloc
038   * @see #malloc
039   */
040  public abstract void free(Address addr);
041
042  /**
043   * Dump a range in format [start,end)
044   *
045   * @param start The start of the range
046   * @param end The end of the range
047   */
048  public static void dumpRange(Address start, Address end) {
049    Log.write("["); Log.write(start);
050    Log.write(","); Log.write(end);
051    Log.write(')');
052  }
053
054  /**
055   * Convert a String to a 0-terminated array of bytes
056   *
057   * @param str The string to convert
058   * @return The address of a null-terminated array in C-space
059   */
060  public abstract Address getBytes(String str);
061
062  /**
063   * Pretty print a size, converting from bytes to kilo- or mega-bytes as appropriate
064   *
065   * @param buffer The buffer (in C space) in which to place the formatted size
066   * @param size The size in bytes
067   */
068  public abstract void formatSize(Address buffer, int size);
069
070  /**
071   * Pretty print a size, converting from bytes to kilo- or mega-bytes as appropriate
072   *
073   * @param format A format string
074   * @param bufsize The size of a buffer large enough to hold the formatted result
075   * @param size The size in bytes
076   * @return start address of the buffer allocated by this call
077   */
078  public abstract Address formatSize(String format, int bufsize, int size);
079
080  /**
081   * Place a string representation of a long in an array of bytes
082   * without incurring allocation
083   *
084   * @param buffer The byte array
085   * @param value The long to convert
086   * @return The length of the string representation of the integer
087   *         -1 indicates some problem (e.g the char buffer was too small)
088   */
089  public static int numToBytes(byte[] buffer, long value) {
090    return numToBytes(buffer, value, 10);
091  }
092
093  /**
094   * Place a string representation of a long in an array of bytes
095   * without incurring allocation
096   *
097   * @param buffer The byte array
098   * @param value The long to convert
099   * @param radix the base to use for conversion
100   * @return The length of the string representation of the integer
101   *         -1 indicates some problem (e.g the char buffer was too small)
102   */
103  public static int numToBytes(byte[] buffer, long value, int radix) {
104
105    if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX)
106      radix = 10;
107
108    if (value == 0) {
109      buffer[0] = (byte)'0';
110      return 1;
111    }
112
113    boolean negative;
114    long longValue;
115    int count;
116    if (!(negative = (value < 0))) {
117      longValue = -value;
118      count = 1;
119    } else {
120      longValue = value;
121      count = 2;
122    }
123
124    long j = longValue;
125    while ((j /= radix) != 0) count++;
126    if (count > buffer.length)
127      return -1; // overflow
128
129    int i = count;
130    do {
131      int ch = (int) -(longValue % radix);
132      if (ch > 9)
133        ch -= (10 - 'a');
134      else
135        ch += '0';
136      buffer [--i] = (byte) ch;
137    } while ((longValue /= radix) != 0);
138    if (negative) buffer [0] = (byte)'-';
139
140    return count;
141
142  }
143
144  /**
145   * {@code sprintf(char *str, char *format, char* value)}
146   *
147   * @param str The destination 'string' (memory in C space)
148   * @param format The format 'string' (memory in C space)
149   * @param value The value 'string' (memory in C space)
150   * @return The number of characters printed (as returned by C's sprintf
151   */
152  public abstract int sprintf(Address str, Address format, Address value);
153
154  /**
155   * Create an array of a particular type.
156   * The easiest way to use this is:
157   *     {@code Foo[] x = (Foo [])Stream.createDataArray(new Foo[0], numElements);}
158   * @param templ a data array to use as a template
159   * @param numElements number of elements in new array
160   * @return the new array
161   */
162  @Interruptible
163  public abstract Object createDataArray(Object templ, int numElements);
164}
165