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.utility.alloc;
014    
015    import org.mmtk.policy.SegregatedFreeListSpace;
016    import org.mmtk.utility.*;
017    
018    import org.vmmagic.pragma.*;
019    import org.vmmagic.unboxed.*;
020    
021    /**
022     * This abstract class implements the fast past for a segregated free list.
023     */
024    @Uninterruptible
025    public abstract class SegregatedFreeList<S extends SegregatedFreeListSpace> extends Allocator implements Constants {
026    
027      /****************************************************************************
028       *
029       * Instance variables
030       */
031    
032      /** The space */
033      protected final S space;
034    
035      /** The current free lists for the size classes */
036      protected final AddressArray freeList;
037    
038      /****************************************************************************
039       *
040       * Initialization
041       */
042    
043      /**
044       * Constructor
045       *
046       * @param space The space with which this allocator will be associated
047       */
048      public SegregatedFreeList(S space) {
049        this.space = space;
050        this.freeList = AddressArray.create(sizeClassCount());
051      }
052    
053      /**
054       * Return the space this allocator is currently bound to.
055       *
056       * @return The Space.
057       */
058      protected final S getSpace() {
059        return this.space;
060      }
061    
062      /****************************************************************************
063       *
064       * Allocation
065       */
066    
067      /**
068       * Allocate <code>bytes</code> contiguous bytes of zeroed memory.<p>
069       *
070       * This code implements the fast path, and on failure delegates to the slow path.
071       *
072       * @param bytes The size of the object to occupy this space, in bytes.
073       * @param align The requested alignment.
074       * @param offset The alignment offset.
075       * @return The address of the first word or zero on failure
076       */
077      @Inline
078      public final Address alloc(int bytes, int align, int offset) {
079        int alignedBytes = getMaximumAlignedSize(bytes, align);
080        int sizeClass = getSizeClass(alignedBytes);
081        Address cell = freeList.get(sizeClass);
082        if (!cell.isZero()) {
083          freeList.set(sizeClass, cell.loadAddress());
084          /* Clear the free list link */
085          cell.store(Address.zero());
086          if (alignedBytes != bytes) {
087            /* Ensure aligned as requested. */
088            cell = alignAllocation(cell, align, offset);
089          }
090          return cell;
091        }
092        return allocSlow(bytes, align, offset);
093      }
094    
095      /**
096       * The number of distinct size classes.
097       *
098       * NOTE: For optimal performance this call must be implemented in a way
099       * it can be inlined and optimized within the allocation sequence.
100       */
101      @Inline
102      private int sizeClassCount() {
103        return SegregatedFreeListSpace.sizeClassCount();
104      }
105    
106      /**
107       * Get the size class for a given number of bytes.
108       *
109       * NOTE: For optimal performance this call must be implemented in a way
110       * it can be inlined and optimized within the allocation sequence.
111       *
112       * @param bytes The number of bytes required to accommodate the object
113       * @return The size class capable of accommodating the allocation request.
114       */
115      @Inline
116      private int getSizeClass(int bytes) {
117        return space.getSizeClass(bytes);
118      }
119    }