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