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; 014 015import static org.jikesrvm.objectmodel.JavaHeaderConstants.ARRAY_BASE_OFFSET; 016import static org.jikesrvm.objectmodel.JavaHeaderConstants.GC_HEADER_OFFSET; 017 018import org.jikesrvm.classloader.Atom; 019import org.jikesrvm.classloader.RVMArray; 020import org.jikesrvm.classloader.RVMClass; 021import org.jikesrvm.classloader.RVMType; 022import org.jikesrvm.mm.mminterface.DebugUtil; 023import org.jikesrvm.mm.mminterface.MemoryManager; 024import org.jikesrvm.objectmodel.TIB; 025import org.jikesrvm.runtime.Magic; 026import org.mmtk.plan.CollectorContext; 027import org.mmtk.utility.alloc.Allocator; 028import org.mmtk.vm.VM; 029import org.vmmagic.pragma.Inline; 030import org.vmmagic.pragma.Uninterruptible; 031import org.vmmagic.unboxed.Address; 032import org.vmmagic.unboxed.ObjectReference; 033import org.vmmagic.unboxed.Offset; 034import org.vmmagic.unboxed.Word; 035 036@Uninterruptible public final class ObjectModel extends org.mmtk.vm.ObjectModel { 037 038 @Override 039 protected Offset getArrayBaseOffset() { 040 return ARRAY_BASE_OFFSET; 041 } 042 043 @Override 044 @Inline 045 public ObjectReference copy(ObjectReference from, int allocator) { 046 TIB tib = org.jikesrvm.objectmodel.ObjectModel.getTIB(from); 047 RVMType type = Magic.objectAsType(tib.getType()); 048 049 if (type.isClassType()) 050 return copyScalar(from, tib, type.asClass(), allocator); 051 else 052 return copyArray(from, tib, type.asArray(), allocator); 053 } 054 055 @Inline 056 private ObjectReference copyScalar(ObjectReference from, TIB tib, RVMClass type, int allocator) { 057 int bytes = org.jikesrvm.objectmodel.ObjectModel.bytesRequiredWhenCopied(from.toObject(), type); 058 int align = org.jikesrvm.objectmodel.ObjectModel.getAlignment(type, from.toObject()); 059 int offset = org.jikesrvm.objectmodel.ObjectModel.getOffsetForAlignment(type, from); 060 CollectorContext context = VM.activePlan.collector(); 061 allocator = context.copyCheckAllocator(from, bytes, align, allocator); 062 Address region = MemoryManager.allocateSpace(context, bytes, align, offset, 063 allocator, from); 064 Object toObj = org.jikesrvm.objectmodel.ObjectModel.moveObject(region, from.toObject(), bytes, type); 065 ObjectReference to = ObjectReference.fromObject(toObj); 066 context.postCopy(to, ObjectReference.fromObject(tib), bytes, allocator); 067 return to; 068 } 069 070 @Inline 071 private ObjectReference copyArray(ObjectReference from, TIB tib, RVMArray type, int allocator) { 072 int elements = Magic.getArrayLength(from.toObject()); 073 int bytes = org.jikesrvm.objectmodel.ObjectModel.bytesRequiredWhenCopied(from.toObject(), type, elements); 074 int align = org.jikesrvm.objectmodel.ObjectModel.getAlignment(type, from.toObject()); 075 int offset = org.jikesrvm.objectmodel.ObjectModel.getOffsetForAlignment(type, from); 076 CollectorContext context = VM.activePlan.collector(); 077 allocator = context.copyCheckAllocator(from, bytes, align, allocator); 078 Address region = MemoryManager.allocateSpace(context, bytes, align, offset, 079 allocator, from); 080 Object toObj = org.jikesrvm.objectmodel.ObjectModel.moveObject(region, from.toObject(), bytes, type); 081 ObjectReference to = ObjectReference.fromObject(toObj); 082 context.postCopy(to, ObjectReference.fromObject(tib), bytes, allocator); 083 if (type == RVMType.CodeArrayType) { 084 // sync all moved code arrays to get icache and dcache in sync 085 // immediately. 086 int dataSize = bytes - org.jikesrvm.objectmodel.ObjectModel.computeHeaderSize(Magic.getObjectType(toObj)); 087 org.jikesrvm.runtime.Memory.sync(to.toAddress(), dataSize); 088 } 089 return to; 090 } 091 092 /** 093 * Return the size of a given object, in bytes 094 * 095 * @param object The object whose size is being queried 096 * @return The size (in bytes) of the given object. 097 */ 098 static int getObjectSize(ObjectReference object) { 099 TIB tib = org.jikesrvm.objectmodel.ObjectModel.getTIB(object); 100 RVMType type = Magic.objectAsType(tib.getType()); 101 102 if (type.isClassType()) 103 return org.jikesrvm.objectmodel.ObjectModel.bytesRequiredWhenCopied(object.toObject(), type.asClass()); 104 else 105 return org.jikesrvm.objectmodel.ObjectModel.bytesRequiredWhenCopied(object.toObject(), type.asArray(), Magic.getArrayLength(object.toObject())); 106 } 107 108 /** 109 * @param region The start (or an address less than) the region that was reserved for this object. 110 */ 111 @Override 112 @Inline 113 public Address copyTo(ObjectReference from, ObjectReference to, Address region) { 114 TIB tib = org.jikesrvm.objectmodel.ObjectModel.getTIB(from); 115 RVMType type = tib.getType(); 116 int bytes; 117 118 boolean copy = (from != to); 119 120 if (copy) { 121 if (type.isClassType()) { 122 RVMClass classType = type.asClass(); 123 bytes = org.jikesrvm.objectmodel.ObjectModel.bytesRequiredWhenCopied(from.toObject(), classType); 124 org.jikesrvm.objectmodel.ObjectModel.moveObject(from.toObject(), to.toObject(), bytes, classType); 125 } else { 126 RVMArray arrayType = type.asArray(); 127 int elements = Magic.getArrayLength(from.toObject()); 128 bytes = org.jikesrvm.objectmodel.ObjectModel.bytesRequiredWhenCopied(from.toObject(), arrayType, elements); 129 org.jikesrvm.objectmodel.ObjectModel.moveObject(from.toObject(), to.toObject(), bytes, arrayType); 130 } 131 } else { 132 bytes = getCurrentSize(to); 133 } 134 135 Address start = org.jikesrvm.objectmodel.ObjectModel.objectStartRef(to); 136 Allocator.fillAlignmentGap(region, start); 137 138 return start.plus(bytes); 139 } 140 141 @Override 142 public ObjectReference getReferenceWhenCopiedTo(ObjectReference from, Address to) { 143 return ObjectReference.fromObject(org.jikesrvm.objectmodel.ObjectModel.getReferenceWhenCopiedTo(from.toObject(), to)); 144 } 145 146 @Override 147 public Address getObjectEndAddress(ObjectReference object) { 148 return org.jikesrvm.objectmodel.ObjectModel.getObjectEndAddress(object.toObject()); 149 } 150 151 @Override 152 public int getSizeWhenCopied(ObjectReference object) { 153 return org.jikesrvm.objectmodel.ObjectModel.bytesRequiredWhenCopied(object.toObject()); 154 } 155 156 @Override 157 public int getAlignWhenCopied(ObjectReference object) { 158 TIB tib = org.jikesrvm.objectmodel.ObjectModel.getTIB(object); 159 RVMType type = tib.getType(); 160 if (type.isArrayType()) { 161 return org.jikesrvm.objectmodel.ObjectModel.getAlignment(type.asArray(), object.toObject()); 162 } else { 163 return org.jikesrvm.objectmodel.ObjectModel.getAlignment(type.asClass(), object.toObject()); 164 } 165 } 166 167 @Override 168 public int getAlignOffsetWhenCopied(ObjectReference object) { 169 TIB tib = org.jikesrvm.objectmodel.ObjectModel.getTIB(object); 170 RVMType type = tib.getType(); 171 if (type.isArrayType()) { 172 return org.jikesrvm.objectmodel.ObjectModel.getOffsetForAlignment(type.asArray(), object); 173 } else { 174 return org.jikesrvm.objectmodel.ObjectModel.getOffsetForAlignment(type.asClass(), object); 175 } 176 } 177 178 @Override 179 public int getCurrentSize(ObjectReference object) { 180 return org.jikesrvm.objectmodel.ObjectModel.bytesUsed(object.toObject()); 181 } 182 183 @Override 184 public ObjectReference getNextObject(ObjectReference object) { 185 return org.jikesrvm.objectmodel.ObjectModel.getNextObject(object); 186 } 187 188 @Override 189 public ObjectReference getObjectFromStartAddress(Address start) { 190 return org.jikesrvm.objectmodel.ObjectModel.getObjectFromStartAddress(start); 191 } 192 193 @Override 194 public byte [] getTypeDescriptor(ObjectReference ref) { 195 Atom descriptor = Magic.getObjectType(ref).getDescriptor(); 196 return descriptor.toByteArray(); 197 } 198 199 @Override 200 @Inline 201 public int getArrayLength(ObjectReference object) { 202 return Magic.getArrayLength(object.toObject()); 203 } 204 205 @Override 206 public boolean isArray(ObjectReference object) { 207 return org.jikesrvm.objectmodel.ObjectModel.getObjectType(object.toObject()).isArrayType(); 208 } 209 210 @Override 211 public boolean isPrimitiveArray(ObjectReference object) { 212 Object obj = object.toObject(); 213 return (obj instanceof long[] || 214 obj instanceof int[] || 215 obj instanceof short[] || 216 obj instanceof byte[] || 217 obj instanceof double[] || 218 obj instanceof float[]); 219 } 220 221 /** 222 * Tests a bit available for memory manager use in an object. 223 * 224 * @param object the address of the object 225 * @param idx the index of the bit 226 * @return {@code true} if argument bit is 1, {@code false} if it is 0 227 */ 228 public boolean testAvailableBit(ObjectReference object, int idx) { 229 return org.jikesrvm.objectmodel.ObjectModel.testAvailableBit(object.toObject(), idx); 230 } 231 232 /** 233 * Sets a bit available for memory manager use in an object. 234 * 235 * @param object the address of the object 236 * @param idx the index of the bit 237 * @param flag <code>true</code> to set the bit to 1, 238 * <code>false</code> to set it to 0 239 */ 240 public void setAvailableBit(ObjectReference object, int idx, 241 boolean flag) { 242 org.jikesrvm.objectmodel.ObjectModel.setAvailableBit(object.toObject(), idx, flag); 243 } 244 245 @Override 246 public boolean attemptAvailableBits(ObjectReference object, 247 Word oldVal, Word newVal) { 248 return org.jikesrvm.objectmodel.ObjectModel.attemptAvailableBits(object.toObject(), oldVal, 249 newVal); 250 } 251 252 @Override 253 public Word prepareAvailableBits(ObjectReference object) { 254 return org.jikesrvm.objectmodel.ObjectModel.prepareAvailableBits(object.toObject()); 255 } 256 257 @Override 258 public void writeAvailableByte(ObjectReference object, byte val) { 259 org.jikesrvm.objectmodel.ObjectModel.writeAvailableByte(object.toObject(), val); 260 } 261 262 @Override 263 public byte readAvailableByte(ObjectReference object) { 264 return org.jikesrvm.objectmodel.ObjectModel.readAvailableByte(object.toObject()); 265 } 266 267 @Override 268 public void writeAvailableBitsWord(ObjectReference object, Word val) { 269 org.jikesrvm.objectmodel.ObjectModel.writeAvailableBitsWord(object.toObject(), val); 270 } 271 272 @Override 273 public Word readAvailableBitsWord(ObjectReference object) { 274 return org.jikesrvm.objectmodel.ObjectModel.readAvailableBitsWord(object.toObject()); 275 } 276 277 /* AJG: Should this be a variable rather than method? */ 278 @Override 279 public Offset GC_HEADER_OFFSET() { 280 return GC_HEADER_OFFSET; 281 } 282 283 @Override 284 @Inline 285 public Address objectStartRef(ObjectReference object) { 286 return org.jikesrvm.objectmodel.ObjectModel.objectStartRef(object); 287 } 288 289 @Override 290 public Address refToAddress(ObjectReference object) { 291 return org.jikesrvm.objectmodel.ObjectModel.getPointerInMemoryRegion(object); 292 } 293 294 @Override 295 @Inline 296 public boolean isAcyclic(ObjectReference typeRef) { 297 TIB tib = Magic.addressAsTIB(typeRef.toAddress()); 298 RVMType type = tib.getType(); 299 return type.isAcyclicReference(); 300 } 301 302 @Override 303 public void dumpObject(ObjectReference object) { 304 DebugUtil.dumpRef(object); 305 } 306} 307