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;
014
015 import org.mmtk.utility.alloc.Allocator;
016
017 import org.jikesrvm.runtime.Magic;
018 import org.jikesrvm.objectmodel.JavaHeaderConstants;
019 import org.jikesrvm.objectmodel.TIB;
020 import org.jikesrvm.classloader.Atom;
021 import org.jikesrvm.classloader.RVMArray;
022 import org.jikesrvm.classloader.RVMClass;
023 import org.jikesrvm.classloader.RVMType;
024 import org.jikesrvm.mm.mminterface.Selected;
025 import org.jikesrvm.mm.mminterface.DebugUtil;
026 import org.jikesrvm.mm.mminterface.MemoryManager;
027
028 import org.vmmagic.unboxed.*;
029 import org.vmmagic.pragma.*;
030
031 @Uninterruptible public final class ObjectModel extends org.mmtk.vm.ObjectModel implements org.mmtk.utility.Constants,
032 org.jikesrvm.Constants {
033
034 protected Offset getArrayBaseOffset() { return JavaHeaderConstants.ARRAY_BASE_OFFSET; }
035
036 /**
037 * Copy an object using a plan's allocCopy to get space and install
038 * the forwarding pointer. On entry, <code>from</code> must have
039 * been reserved for copying by the caller. This method calls the
040 * plan's <code>getStatusForCopy()</code> method to establish a new
041 * status word for the copied object and <code>postCopy()</code> to
042 * allow the plan to perform any post copy actions.
043 *
044 * @param from the address of the object to be copied
045 * @return the address of the new object
046 */
047 @Inline
048 public ObjectReference copy(ObjectReference from, int allocator) {
049 TIB tib = org.jikesrvm.objectmodel.ObjectModel.getTIB(from);
050 RVMType type = Magic.objectAsType(tib.getType());
051
052 if (type.isClassType())
053 return copyScalar(from, tib, type.asClass(), allocator);
054 else
055 return copyArray(from, tib, type.asArray(), allocator);
056 }
057
058 @Inline
059 private ObjectReference copyScalar(ObjectReference from, TIB tib, RVMClass type, int allocator) {
060 int bytes = org.jikesrvm.objectmodel.ObjectModel.bytesRequiredWhenCopied(from.toObject(), type);
061 int align = org.jikesrvm.objectmodel.ObjectModel.getAlignment(type, from.toObject());
062 int offset = org.jikesrvm.objectmodel.ObjectModel.getOffsetForAlignment(type, from);
063 Selected.Collector plan = Selected.Collector.get();
064 allocator = plan.copyCheckAllocator(from, bytes, align, allocator);
065 Address region = MemoryManager.allocateSpace(plan, bytes, align, offset,
066 allocator, from);
067 Object toObj = org.jikesrvm.objectmodel.ObjectModel.moveObject(region, from.toObject(), bytes, type);
068 ObjectReference to = ObjectReference.fromObject(toObj);
069 plan.postCopy(to, ObjectReference.fromObject(tib), bytes, allocator);
070 return to;
071 }
072
073 @Inline
074 private ObjectReference copyArray(ObjectReference from, TIB tib, RVMArray type, int allocator) {
075 int elements = Magic.getArrayLength(from.toObject());
076 int bytes = org.jikesrvm.objectmodel.ObjectModel.bytesRequiredWhenCopied(from.toObject(), type, elements);
077 int align = org.jikesrvm.objectmodel.ObjectModel.getAlignment(type, from.toObject());
078 int offset = org.jikesrvm.objectmodel.ObjectModel.getOffsetForAlignment(type, from);
079 Selected.Collector plan = Selected.Collector.get();
080 allocator = plan.copyCheckAllocator(from, bytes, align, allocator);
081 Address region = MemoryManager.allocateSpace(plan, bytes, align, offset,
082 allocator, from);
083 Object toObj = org.jikesrvm.objectmodel.ObjectModel.moveObject(region, from.toObject(), bytes, type);
084 ObjectReference to = ObjectReference.fromObject(toObj);
085 plan.postCopy(to, ObjectReference.fromObject(tib), bytes, allocator);
086 if (type == RVMType.CodeArrayType) {
087 // sync all moved code arrays to get icache and dcache in sync
088 // immediately.
089 int dataSize = bytes - org.jikesrvm.objectmodel.ObjectModel.computeHeaderSize(Magic.getObjectType(toObj));
090 org.jikesrvm.runtime.Memory.sync(to.toAddress(), dataSize);
091 }
092 return to;
093 }
094
095 /**
096 * Return the size of a given object, in bytes
097 *
098 * @param object The object whose size is being queried
099 * @return The size (in bytes) of the given object.
100 */
101 static int getObjectSize(ObjectReference object) {
102 TIB tib = org.jikesrvm.objectmodel.ObjectModel.getTIB(object);
103 RVMType type = Magic.objectAsType(tib.getType());
104
105 if (type.isClassType())
106 return org.jikesrvm.objectmodel.ObjectModel.bytesRequiredWhenCopied(object.toObject(), type.asClass());
107 else
108 return org.jikesrvm.objectmodel.ObjectModel.bytesRequiredWhenCopied(object.toObject(), type.asArray(), Magic.getArrayLength(object.toObject()));
109 }
110
111 /**
112 * Copy an object to be pointer to by the to address. This is required
113 * for delayed-copy collectors such as compacting collectors. During the
114 * collection, MMTk reserves a region in the heap for an object as per
115 * requirements found from ObjectModel and then asks ObjectModel to
116 * determine what the object's reference will be post-copy.
117 *
118 * @param from the address of the object to be copied
119 * @param to The target location.
120 * @param region The start (or an address less than) the region that was reserved for this object.
121 * @return Address The address past the end of the copied object
122 */
123 @Inline
124 public Address copyTo(ObjectReference from, ObjectReference to, Address region) {
125 TIB tib = org.jikesrvm.objectmodel.ObjectModel.getTIB(from);
126 RVMType type = tib.getType();
127 int bytes;
128
129 boolean copy = (from != to);
130
131 if (copy) {
132 if (type.isClassType()) {
133 RVMClass classType = type.asClass();
134 bytes = org.jikesrvm.objectmodel.ObjectModel.bytesRequiredWhenCopied(from.toObject(), classType);
135 org.jikesrvm.objectmodel.ObjectModel.moveObject(from.toObject(), to.toObject(), bytes, classType);
136 } else {
137 RVMArray arrayType = type.asArray();
138 int elements = Magic.getArrayLength(from.toObject());
139 bytes = org.jikesrvm.objectmodel.ObjectModel.bytesRequiredWhenCopied(from.toObject(), arrayType, elements);
140 org.jikesrvm.objectmodel.ObjectModel.moveObject(from.toObject(), to.toObject(), bytes, arrayType);
141 }
142 } else {
143 bytes = getCurrentSize(to);
144 }
145
146 Address start = org.jikesrvm.objectmodel.ObjectModel.objectStartRef(to);
147 Allocator.fillAlignmentGap(region, start);
148
149 return start.plus(bytes);
150 }
151
152 /**
153 * Return the reference that an object will be refered to after it is copied
154 * to the specified region. Used in delayed-copy collectors such as compacting
155 * collectors.
156 *
157 * @param from The object to be copied.
158 * @param to The region to be copied to.
159 * @return The resulting reference.
160 */
161 public ObjectReference getReferenceWhenCopiedTo(ObjectReference from, Address to) {
162 return ObjectReference.fromObject(org.jikesrvm.objectmodel.ObjectModel.getReferenceWhenCopiedTo(from.toObject(), to));
163 }
164
165 /**
166 * Gets a pointer to the address just past the end of the object.
167 *
168 * @param object The objecty.
169 */
170 public Address getObjectEndAddress(ObjectReference object) {
171 return org.jikesrvm.objectmodel.ObjectModel.getObjectEndAddress(object.toObject());
172 }
173
174 /**
175 * Return the size required to copy an object
176 *
177 * @param object The object whose size is to be queried
178 * @return The size required to copy <code>obj</code>
179 */
180 public int getSizeWhenCopied(ObjectReference object) {
181 return org.jikesrvm.objectmodel.ObjectModel.bytesRequiredWhenCopied(object.toObject());
182 }
183
184 /**
185 * Return the alignment requirement for a copy of this object
186 *
187 * @param object The object whose size is to be queried
188 * @return The alignment required for a copy of <code>obj</code>
189 */
190 public int getAlignWhenCopied(ObjectReference object) {
191 TIB tib = org.jikesrvm.objectmodel.ObjectModel.getTIB(object);
192 RVMType type = tib.getType();
193 if (type.isArrayType()) {
194 return org.jikesrvm.objectmodel.ObjectModel.getAlignment(type.asArray(), object.toObject());
195 } else {
196 return org.jikesrvm.objectmodel.ObjectModel.getAlignment(type.asClass(), object.toObject());
197 }
198 }
199
200 /**
201 * Return the alignment offset requirements for a copy of this object
202 *
203 * @param object The object whose size is to be queried
204 * @return The alignment offset required for a copy of <code>obj</code>
205 */
206 public int getAlignOffsetWhenCopied(ObjectReference object) {
207 TIB tib = org.jikesrvm.objectmodel.ObjectModel.getTIB(object);
208 RVMType type = tib.getType();
209 if (type.isArrayType()) {
210 return org.jikesrvm.objectmodel.ObjectModel.getOffsetForAlignment(type.asArray(), object);
211 } else {
212 return org.jikesrvm.objectmodel.ObjectModel.getOffsetForAlignment(type.asClass(), object);
213 }
214 }
215
216 /**
217 * Return the size used by an object
218 *
219 * @param object The object whose size is to be queried
220 * @return The size of <code>obj</code>
221 */
222 public int getCurrentSize(ObjectReference object) {
223 return org.jikesrvm.objectmodel.ObjectModel.bytesUsed(object.toObject());
224 }
225
226 /**
227 * Return the next object in the heap under contiguous allocation
228 */
229 public ObjectReference getNextObject(ObjectReference object) {
230 return org.jikesrvm.objectmodel.ObjectModel.getNextObject(object);
231 }
232
233 /**
234 * Return an object reference from knowledge of the low order word
235 */
236 public ObjectReference getObjectFromStartAddress(Address start) {
237 return org.jikesrvm.objectmodel.ObjectModel.getObjectFromStartAddress(start);
238 }
239
240 /**
241 * Get the type descriptor for an object.
242 *
243 * @param ref address of the object
244 * @return byte array with the type descriptor
245 */
246 public byte [] getTypeDescriptor(ObjectReference ref) {
247 Atom descriptor = Magic.getObjectType(ref).getDescriptor();
248 return descriptor.toByteArray();
249 }
250
251 @Inline
252 public int getArrayLength(ObjectReference object) {
253 return Magic.getArrayLength(object.toObject());
254 }
255
256 /**
257 * Is the passed object an array?
258 *
259 * @param object address of the object
260 */
261 public boolean isArray(ObjectReference object) {
262 return org.jikesrvm.objectmodel.ObjectModel.getObjectType(object.toObject()).isArrayType();
263 }
264
265 /**
266 * Is the passed object a primitive array?
267 *
268 * @param object address of the object
269 */
270 public boolean isPrimitiveArray(ObjectReference object) {
271 Object obj = object.toObject();
272 return (obj instanceof long[] ||
273 obj instanceof int[] ||
274 obj instanceof short[] ||
275 obj instanceof byte[] ||
276 obj instanceof double[] ||
277 obj instanceof float[]);
278 }
279
280 /**
281 * Tests a bit available for memory manager use in an object.
282 *
283 * @param object the address of the object
284 * @param idx the index of the bit
285 */
286 public boolean testAvailableBit(ObjectReference object, int idx) {
287 return org.jikesrvm.objectmodel.ObjectModel.testAvailableBit(object.toObject(), idx);
288 }
289
290 /**
291 * Sets a bit available for memory manager use in an object.
292 *
293 * @param object the address of the object
294 * @param idx the index of the bit
295 * @param flag <code>true</code> to set the bit to 1,
296 * <code>false</code> to set it to 0
297 */
298 public void setAvailableBit(ObjectReference object, int idx,
299 boolean flag) {
300 org.jikesrvm.objectmodel.ObjectModel.setAvailableBit(object.toObject(), idx, flag);
301 }
302
303 /**
304 * Attempts to set the bits available for memory manager use in an
305 * object. The attempt will only be successful if the current value
306 * of the bits matches <code>oldVal</code>. The comparison with the
307 * current value and setting are atomic with respect to other
308 * allocators.
309 *
310 * @param object the address of the object
311 * @param oldVal the required current value of the bits
312 * @param newVal the desired new value of the bits
313 * @return <code>true</code> if the bits were set,
314 * <code>false</code> otherwise
315 */
316 public boolean attemptAvailableBits(ObjectReference object,
317 Word oldVal, Word newVal) {
318 return org.jikesrvm.objectmodel.ObjectModel.attemptAvailableBits(object.toObject(), oldVal,
319 newVal);
320 }
321
322 /**
323 * Gets the value of bits available for memory manager use in an
324 * object, in preparation for setting those bits.
325 *
326 * @param object the address of the object
327 * @return the value of the bits
328 */
329 public Word prepareAvailableBits(ObjectReference object) {
330 return org.jikesrvm.objectmodel.ObjectModel.prepareAvailableBits(object.toObject());
331 }
332
333 /**
334 * Sets the byte available for memory manager use in an object.
335 *
336 * @param object the address of the object
337 * @param val the new value of the byte
338 */
339 public void writeAvailableByte(ObjectReference object, byte val) {
340 org.jikesrvm.objectmodel.ObjectModel.writeAvailableByte(object.toObject(), val);
341 }
342
343 /**
344 * Read the byte available for memory manager use in an object.
345 *
346 * @param object the address of the object
347 * @return the value of the byte
348 */
349 public byte readAvailableByte(ObjectReference object) {
350 return org.jikesrvm.objectmodel.ObjectModel.readAvailableByte(object.toObject());
351 }
352
353 /**
354 * Sets the bits available for memory manager use in an object.
355 *
356 * @param object the address of the object
357 * @param val the new value of the bits
358 */
359 public void writeAvailableBitsWord(ObjectReference object, Word val) {
360 org.jikesrvm.objectmodel.ObjectModel.writeAvailableBitsWord(object.toObject(), val);
361 }
362
363 /**
364 * Read the bits available for memory manager use in an object.
365 *
366 * @param object the address of the object
367 * @return the value of the bits
368 */
369 public Word readAvailableBitsWord(ObjectReference object) {
370 return org.jikesrvm.objectmodel.ObjectModel.readAvailableBitsWord(object.toObject());
371 }
372
373 /**
374 * Gets the offset of the memory management header from the object
375 * reference address. XXX The object model / memory manager
376 * interface should be improved so that the memory manager does not
377 * need to know this.
378 *
379 * @return the offset, relative the object reference address
380 */
381 /* AJG: Should this be a variable rather than method? */
382 public Offset GC_HEADER_OFFSET() {
383 return org.jikesrvm.objectmodel.ObjectModel.GC_HEADER_OFFSET;
384 }
385
386 /**
387 * Returns the lowest address of the storage associated with an object.
388 *
389 * @param object the reference address of the object
390 * @return the lowest address of the object
391 */
392 @Inline
393 public Address objectStartRef(ObjectReference object) {
394 return org.jikesrvm.objectmodel.ObjectModel.objectStartRef(object);
395 }
396
397 /**
398 * Returns an address guaranteed to be inside the storage assocatied
399 * with and object.
400 *
401 * @param object the reference address of the object
402 * @return an address inside the object
403 */
404 public Address refToAddress(ObjectReference object) {
405 return org.jikesrvm.objectmodel.ObjectModel.getPointerInMemoryRegion(object);
406 }
407
408 /**
409 * Checks if a reference of the given type in another object is
410 * inherently acyclic. The type is given as a TIB.
411 *
412 * @return <code>true</code> if a reference of the type is
413 * inherently acyclic
414 */
415 @Inline
416 public boolean isAcyclic(ObjectReference typeRef) {
417 TIB tib = Magic.addressAsTIB(typeRef.toAddress());
418 RVMType type = tib.getType();
419 return type.isAcyclicReference();
420 }
421
422 /**
423 * Dump debugging information for an object.
424 *
425 * @param object The object whose information is to be dumped
426 */
427 public void dumpObject(ObjectReference object) {
428 DebugUtil.dumpRef(object);
429 }
430 }
431