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.jikesrvm.osr;
014
015import static org.jikesrvm.runtime.UnboxedSizeConstants.LOG_BYTES_IN_ADDRESS;
016
017import org.jikesrvm.VM;
018import org.jikesrvm.mm.mminterface.Barriers;
019import org.jikesrvm.runtime.Magic;
020import org.vmmagic.pragma.Inline;
021import org.vmmagic.pragma.Interruptible;
022import org.vmmagic.pragma.Uninterruptible;
023import org.vmmagic.unboxed.Offset;
024
025/**
026 * ObjectHolder helps the specialized prologue to load reference
027 * get around of GC problem.<p>
028 * TODO this class needs better comments.
029 */
030@Uninterruptible
031public class ObjectHolder {
032
033  // initialize pool size
034  private static final int POOLSIZE = 8;
035
036  private static Object[][] refs;
037
038  @Interruptible
039  public static void boot() {
040    refs = new Object[POOLSIZE][];
041
042    // exercise the method to avoid lazy compilation in the future
043    Object[] objs = new Object[1];
044    int p = handinRefs(objs);
045    getRefAt(p, 0);
046    cleanRefs(p);
047
048    if (VM.TraceOnStackReplacement) {
049      VM.sysWriteln("ObjectHolder booted...");
050    }
051  }
052
053  /*
054   * TODO add better documentation and turn this into a JavaDoc comment.
055   *
056   * The VM scope descriptor extractor can hand in an object here
057   */
058  @Interruptible
059  public static int handinRefs(Object[] objs) {
060    int n = refs.length;
061    for (int i = 0; i < n; i++) {
062      if (refs[i] == null) {
063        refs[i] = objs;
064        return i;
065      }
066    }
067    // grow the array
068    Object[][] newRefs = new Object[2 * n][];
069    System.arraycopy(refs, 0, newRefs, 0, n);
070    newRefs[n] = objs;
071    refs = newRefs;
072
073    return n;
074  }
075
076  /*
077   * TODO add better documentation and turn this into a JavaDoc comment.
078   *
079   * Get the object handed in before, only called by specialized code.
080   */
081  @Inline
082  public static Object getRefAt(int h, int i) {
083
084    if (VM.TraceOnStackReplacement) {
085      VM.sysWriteln("ObjectHolder getRefAt");
086    }
087    Object obj = refs[h][i];
088    return obj;
089  }
090
091  /*
092   * TODO add better documentation and turn this into a JavaDoc comment.
093   *
094   * Clean objects. This method is called by specialized bytecode prologue
095   * Uses magic because it must be uninterruptible
096   */
097  @Inline
098  public static void cleanRefs(int h) {
099    if (VM.TraceOnStackReplacement) {
100      VM.sysWriteln("ObjectHolder cleanRefs");
101    }
102    /* refs[h] = null; */
103    if (Barriers.NEEDS_OBJECT_ASTORE_BARRIER) {
104      Barriers.objectArrayWrite(refs, h, null);
105    } else {
106      Magic.setObjectAtOffset(refs, Offset.fromIntSignExtend(h << LOG_BYTES_IN_ADDRESS), null);
107    }
108  }
109}