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.mmtk.policy;
014    
015    import org.mmtk.plan.TransitiveClosure;
016    import org.mmtk.utility.heap.FreeListPageResource;
017    import org.mmtk.utility.heap.VMRequest;
018    import org.mmtk.utility.DoublyLinkedList;
019    
020    import org.mmtk.vm.VM;
021    
022    import org.vmmagic.pragma.*;
023    import org.vmmagic.unboxed.*;
024    
025    /**
026     * Each instance of this class corresponds to one explicitly managed
027     * large object space.
028     */
029    @Uninterruptible
030    public final class ExplicitLargeObjectSpace extends BaseLargeObjectSpace {
031    
032      /****************************************************************************
033       *
034       * Instance variables
035       */
036    
037      /**
038       *
039       */
040      private final DoublyLinkedList cells;
041    
042      /****************************************************************************
043       *
044       * Initialization
045       */
046    
047      /**
048       * The caller specifies the region of virtual memory to be used for
049       * this space.  If this region conflicts with an existing space,
050       * then the constructor will fail.
051       *
052       * @param name The name of this space (used when printing error messages etc)
053       * @param vmRequest An object describing the virtual memory requested.
054       */
055      public ExplicitLargeObjectSpace(String name, VMRequest vmRequest) {
056        this(name, true, vmRequest);
057      }
058    
059      /**
060       * The caller specifies the region of virtual memory to be used for
061       * this space.  If this region conflicts with an existing space,
062       * then the constructor will fail.
063       *
064       * @param name The name of this space (used when printing error messages etc)
065       * @param zeroed if {@code true}, allocations return zeroed memory.
066       * @param vmRequest An object describing the virtual memory requested.
067       */
068      public ExplicitLargeObjectSpace(String name, boolean zeroed, VMRequest vmRequest) {
069        super(name, zeroed, vmRequest);
070        cells = new DoublyLinkedList(LOG_BYTES_IN_PAGE, true);
071      }
072    
073      /****************************************************************************
074       *
075       * Collection
076       */
077    
078      /**
079       * Prepare for a new collection increment.
080       */
081      public void prepare() {
082      }
083    
084      /**
085       * A new collection increment has completed.
086       */
087      public void release() {
088      }
089    
090      /**
091       * Release a group of pages that were allocated together.
092       *
093       * @param first The first page in the group of pages that were
094       * allocated together.
095       */
096      @Override
097      @Inline
098      public void release(Address first) {
099        ((FreeListPageResource) pr).releasePages(first);
100      }
101    
102      /**
103       * Perform any required initialization of the GC portion of the header.
104       *
105       * @param object the object ref to the storage to be initialized
106       * @param alloc is this initialization occuring due to (initial) allocation
107       * ({@code true}) or due to copying (<code>false</code>)?
108       */
109      @Inline
110      public void initializeHeader(ObjectReference object, boolean alloc) {
111        Address cell = VM.objectModel.objectStartRef(object);
112        cells.add(DoublyLinkedList.midPayloadToNode(cell));
113      }
114    
115      /****************************************************************************
116       *
117       * Object processing and tracing
118       */
119    
120      /**
121       * Trace a reference to an object under a mark sweep collection
122       * policy.  If the object header is not already marked, mark the
123       * object in either the bitmap or by moving it off the treadmill,
124       * and enqueue the object for subsequent processing. The object is
125       * marked as (an atomic) side-effect of checking whether already
126       * marked.
127       *
128       * @param trace The trace being conducted.
129       * @param object The object to be traced.
130       * @return The object (there is no object forwarding in this
131       * collector, so we always return the same object: this could be a
132       * void method but for compliance to a more general interface).
133       */
134      @Override
135      @Inline
136      public ObjectReference traceObject(TransitiveClosure trace, ObjectReference object) {
137        return object;
138      }
139    
140      /**
141       * @param object The object in question
142       * @return {@code true} if this object is known to be live (i.e. it is marked)
143       */
144      @Override
145      @Inline
146      public boolean isLive(ObjectReference object) {
147        return true;
148      }
149    
150      @Override
151      @Inline
152      protected int superPageHeaderSize() {
153        return DoublyLinkedList.headerSize();
154      }
155    
156      @Override
157      @Inline
158      protected int cellHeaderSize() { return 0; }
159    
160      /**
161       * Sweep through all the objects in this space.
162       *
163       * @param sweeper The sweeper callback to use.
164       */
165      @Inline
166      public void sweep(Sweeper sweeper) {
167        Address cell = cells.getHead();
168        while (!cell.isZero()) {
169          Address next = cells.getNext(cell);
170          ObjectReference obj = VM.objectModel.getObjectFromStartAddress(cell.plus(DoublyLinkedList.headerSize()));
171          if (sweeper.sweepLargeObject(obj)) {
172            free(obj);
173          }
174          cell = next;
175        }
176      }
177    
178      /**
179       * Free an object
180       *
181       * @param object The object to be freed.
182       */
183      @Inline
184      public void free(ObjectReference object) {
185        Address cell = getSuperPage(VM.objectModel.refToAddress(object));
186        cells.remove(cell);
187        release(cell);
188      }
189    
190      /**
191       * A callback used to perform sweeping of the large object space.
192       */
193      @Uninterruptible
194      public abstract static class Sweeper {
195        public abstract boolean sweepLargeObject(ObjectReference object);
196      }
197    }