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