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