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