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