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.jikesrvm.mm.mmtk.gcspy;
014
015import org.mmtk.utility.Log;
016import org.mmtk.plan.Plan;
017import org.mmtk.vm.VM;
018
019import org.jikesrvm.runtime.Magic;
020import static org.jikesrvm.runtime.SysCall.sysCall;
021import org.jikesrvm.classloader.RVMArray;
022import org.jikesrvm.objectmodel.ObjectModel;
023import org.jikesrvm.runtime.RuntimeEntrypoints;
024
025import org.vmmagic.unboxed.*;
026import org.vmmagic.pragma.*;
027
028/**
029 * This class provides generally useful methods.
030 */
031@Uninterruptible public class Util extends org.mmtk.vm.gcspy.Util {
032  private static final boolean DEBUG_ = false;
033  public static final int KILOBYTE = 1024;
034  public static final int MEGABYTE = 1024 * 1024;
035
036  @Override
037  public final Address malloc(int size) {
038    if (org.jikesrvm.VM.BuildWithGCSpy) {
039      Address rtn  = sysCall.sysMalloc(size);
040      if (rtn.isZero()) VM.assertions.fail("GCspy malloc failure");
041      return rtn;
042    } else
043      return Address.zero();
044  }
045
046  @Override
047  public final void free(Address addr) {
048    if (org.jikesrvm.VM.BuildWithGCSpy)
049      if (!addr.isZero())
050        sysCall.sysFree(addr);
051  }
052
053  /**
054   * Convert a String to a 0-terminated array of bytes
055   * <p>
056   * WARNING: we call out to String.length and String.charAt, both of
057   * which are interruptible. We protect these calls with a
058   * swLock/swUnlock mechanism, as per VM.sysWrite on String.
059   *
060   * @param str The string to convert
061   * @return The address of a null-terminated array in C-space
062   */
063  @Override
064  public final Address getBytes(String str) {
065    if (org.jikesrvm.VM.BuildWithGCSpy) {
066      if (str == null)
067        return Address.zero();
068
069      if (DEBUG_) {
070        Log.write("getBytes: "); Log.write(str); Log.write("->");
071      }
072
073      // Grab some memory sufficient to hold the null terminated string,
074      // rounded up to an integral number of ints.
075      char[] str_backing = java.lang.JikesRVMSupport.getBackingCharArray(str);
076      int str_length = java.lang.JikesRVMSupport.getStringLength(str);
077      int str_offset = java.lang.JikesRVMSupport.getStringOffset(str);
078      int size = (str_length + 4) & -4;
079      Address rtn = malloc(size);
080
081      // Write the string into it, one byte at a time (dodgy conversion)
082      for (int i = 0; i < str_length; i++)  {
083        rtn.store((byte)str_backing[str_offset + i], Offset.fromIntSignExtend(i));
084      }
085      // Zero rest of byte[]
086      for (int i = str_length; i < size; i++)  {
087        rtn.store((byte)0, Offset.fromIntSignExtend(i - str_offset));
088      }
089      if (DEBUG_) {
090        sysCall.sysWriteBytes(2/*SysTraceFd*/, rtn, size); Log.write("\n");
091      }
092      return rtn;
093    } else {
094      return Address.zero();
095    }
096  }
097
098  @Override
099  public final void formatSize(Address buffer, int size) {
100    if (org.jikesrvm.VM.BuildWithGCSpy)
101      sysCall.gcspyFormatSize(buffer, size);
102  }
103
104
105  @Override
106  public final Address formatSize(String format, int bufsize, int size) {
107    if (org.jikesrvm.VM.BuildWithGCSpy) {
108      // - sprintf(tmp, "Current Size: %s\n", gcspy_formatSize(size));
109      Address tmp = malloc(bufsize);
110      Address formattedSize = malloc(bufsize);
111      Address currentSize = getBytes(format);
112      formatSize(formattedSize, size);
113      sprintf(tmp, currentSize, formattedSize);
114      return tmp;
115    } else {
116      return Address.zero();
117    }
118  }
119
120  @Override
121  @Interruptible
122  public Object createDataArray(Object templ, int numElements) {
123    if (org.jikesrvm.VM.BuildWithGCSpy) {
124      RVMArray array = Magic.getObjectType(templ).asArray();
125      return RuntimeEntrypoints.resolvedNewArray(numElements,
126                              array.getLogElementSize(),
127                              ObjectModel.computeArrayHeaderSize(array),
128                              array.getTypeInformationBlock(),
129                              Plan.ALLOC_GCSPY,
130                              ObjectModel.getAlignment(array),
131                              ObjectModel.getOffsetForAlignment(array, false),
132                              0);
133    } else {
134      return null;
135    }
136  }
137
138  //----------- Various methods modelled on string.c ---------------------//
139
140  @Override
141  public final int sprintf(Address str, Address format, Address value) {
142    if (org.jikesrvm.VM.BuildWithGCSpy)
143      return sysCall.gcspySprintf(str, format, value);
144    else
145      return 0;
146  }
147}