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