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