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 /**
038 * Allocate an array of bytes with malloc
039 *
040 * @param size The size to allocate
041 * @return The start address of the memory allocated in C space
042 * @see #free
043 */
044 public final Address malloc(int size) {
045 if (org.jikesrvm.VM.BuildWithGCSpy) {
046 Address rtn = sysCall.sysMalloc(size);
047 if (rtn.isZero()) VM.assertions.fail("GCspy malloc failure");
048 return rtn;
049 } else
050 return Address.zero();
051 }
052
053 /**
054 * Free an array of bytes previously allocated with malloc
055 *
056 * @param addr The address of some memory previously allocated with malloc
057 * @see #malloc
058 */
059 public final void free(Address addr) {
060 if (org.jikesrvm.VM.BuildWithGCSpy)
061 if (!addr.isZero())
062 sysCall.sysFree(addr);
063 }
064
065 /**
066 * Convert a String to a 0-terminated array of bytes
067 *
068 * @param str The string to convert
069 * @return The address of a null-terminated array in C-space
070 *
071 * WARNING: we call out to String.length and String.charAt, both of
072 * which are interruptible. We protect these calls with a
073 * swLock/swUnlock mechanism, as per VM.sysWrite on String
074 */
075 public final Address getBytes(String str) {
076 if (org.jikesrvm.VM.BuildWithGCSpy) {
077 if (str == null)
078 return Address.zero();
079
080 if (DEBUG_) {
081 Log.write("getBytes: "); Log.write(str); Log.write("->");
082 }
083
084 // Grab some memory sufficient to hold the null terminated string,
085 // rounded up to an integral number of ints.
086 char[] str_backing = java.lang.JikesRVMSupport.getBackingCharArray(str);
087 int str_length = java.lang.JikesRVMSupport.getStringLength(str);
088 int str_offset = java.lang.JikesRVMSupport.getStringOffset(str);
089 int size = (str_length + 4) & -4;
090 Address rtn = malloc(size);
091
092 // Write the string into it, one byte at a time (dodgy conversion)
093 for (int i=0; i < str_length; i++) {
094 rtn.store((byte)str_backing[str_offset+i], Offset.fromIntSignExtend(i));
095 }
096 // Zero rest of byte[]
097 for (int i=str_length; i < size; i++) {
098 rtn.store((byte)0, Offset.fromIntSignExtend(i-str_offset));
099 }
100 if (DEBUG_) {
101 sysCall.sysWriteBytes(2/*SysTraceFd*/, rtn, size); Log.write("\n");
102 }
103 return rtn;
104 } else {
105 return Address.zero();
106 }
107 }
108
109 /**
110 * Pretty print a size, converting from bytes to kilo- or mega-bytes as appropriate
111 *
112 * @param buffer The buffer (in C space) in which to place the formatted size
113 * @param size The size in bytes
114 */
115 public final void formatSize(Address buffer, int size) {
116 if (org.jikesrvm.VM.BuildWithGCSpy)
117 sysCall.gcspyFormatSize(buffer, size);
118 }
119
120
121 /**
122 * Pretty print a size, converting from bytes to kilo- or mega-bytes as appropriate
123 *
124 * @param format A format string
125 * @param bufsize The size of a buffer large enough to hold the formatted result
126 * @param size The size in bytes
127 */
128 public final Address formatSize(String format, int bufsize, int size) {
129 if (org.jikesrvm.VM.BuildWithGCSpy) {
130 // - sprintf(tmp, "Current Size: %s\n", gcspy_formatSize(size));
131 Address tmp = malloc(bufsize);
132 Address formattedSize = malloc(bufsize);
133 Address currentSize = getBytes(format);
134 formatSize(formattedSize, size);
135 sprintf(tmp, currentSize, formattedSize);
136 return tmp;
137 } else {
138 return Address.zero();
139 }
140 }
141
142 /**
143 * Create an array of a particular type.
144 * The easiest way to use this is:
145 * Foo[] x = (Foo [])Stream.createDataArray(new Foo[0], numElements);
146 * @param templ a data array to use as a template
147 * @param numElements number of elements in new array
148 * @return the new array
149 */
150 @Interruptible
151 public Object createDataArray(Object templ, int numElements) {
152 if (org.jikesrvm.VM.BuildWithGCSpy) {
153 RVMArray array = Magic.getObjectType(templ).asArray();
154 return RuntimeEntrypoints.resolvedNewArray(numElements,
155 array.getLogElementSize(),
156 ObjectModel.computeArrayHeaderSize(array),
157 array.getTypeInformationBlock(),
158 Plan.ALLOC_GCSPY,
159 ObjectModel.getAlignment(array),
160 ObjectModel.getOffsetForAlignment(array, false),
161 0);
162 } else {
163 return null;
164 }
165 }
166
167 //----------- Various methods modelled on string.c ---------------------//
168
169 /**
170 * sprintf(char *str, char *format, char* value)
171 *
172 * @param str The destination 'string' (memory in C space)
173 * @param format The format 'string' (memory in C space)
174 * @param value The value 'string' (memory in C space)
175 * @return The number of characters printed (as returned by C's sprintf
176 */
177 public final int sprintf(Address str, Address format, Address value) {
178 if (org.jikesrvm.VM.BuildWithGCSpy)
179 return sysCall.gcspySprintf(str, format, value);
180 else
181 return 0;
182 }
183 }