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      @Override
054      protected final S getSpace() {
055        return this.space;
056      }
057    
058      /****************************************************************************
059       *
060       * Allocation
061       */
062    
063      /**
064       * Allocate <code>bytes</code> contiguous bytes of zeroed memory.<p>
065       *
066       * This code implements the fast path, and on failure delegates to the slow path.
067       *
068       * @param bytes The size of the object to occupy this space, in bytes.
069       * @param align The requested alignment.
070       * @param offset The alignment offset.
071       * @return The address of the first word or zero on failure
072       */
073      @Inline
074      public final Address alloc(int bytes, int align, int offset) {
075        int alignedBytes = getMaximumAlignedSize(bytes, align);
076        int sizeClass = getSizeClass(alignedBytes);
077        Address cell = freeList.get(sizeClass);
078        if (!cell.isZero()) {
079          freeList.set(sizeClass, cell.loadAddress());
080          /* Clear the free list link */
081          cell.store(Address.zero());
082          if (alignedBytes != bytes) {
083            /* Ensure aligned as requested. */
084            cell = alignAllocation(cell, align, offset);
085          }
086          return cell;
087        }
088        return allocSlow(bytes, align, offset);
089      }
090    
091      /**
092       * The number of distinct size classes.<p>
093       *
094       * NOTE: For optimal performance this call must be implemented in a way
095       * it can be inlined and optimized within the allocation sequence.
096       */
097      @Inline
098      private int sizeClassCount() {
099        return SegregatedFreeListSpace.sizeClassCount();
100      }
101    
102      /**
103       * Get the size class for a given number of bytes.<p>
104       *
105       * NOTE: For optimal performance this call must be implemented in a way
106       * it can be inlined and optimized within the allocation sequence.
107       *
108       * @param bytes The number of bytes required to accommodate the object
109       * @return The size class capable of accommodating the allocation request.
110       */
111      @Inline
112      private int getSizeClass(int bytes) {
113        return space.getSizeClass(bytes);
114      }
115    }