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.mm.mminterface;
014
015import static org.jikesrvm.runtime.UnboxedSizeConstants.BYTES_IN_ADDRESS;
016
017import org.jikesrvm.classloader.RVMType;
018import org.jikesrvm.objectmodel.JavaHeader;
019import org.jikesrvm.objectmodel.ObjectModel;
020import org.mmtk.plan.TransitiveClosure;
021import org.vmmagic.pragma.Inline;
022import org.vmmagic.pragma.Uninterruptible;
023
024/**
025 * Supply and interpretation of values to be alignment-encoded into
026 * the TIB pointer of an object.
027 */
028public class HandInlinedScanning {
029
030  public static final int AE_FALLBACK = (1 << AlignmentEncoding.FIELD_WIDTH) - 1;
031  public static final int AE_REFARRAY = AE_FALLBACK - 1;
032
033  public static final int AE_PATTERN_0x0  = 0;
034  public static final int AE_PATTERN_0x1  = 1;
035  public static final int AE_PATTERN_0x7  = 2;
036  public static final int AE_PATTERN_0x3F = 3;
037  public static final int AE_PATTERN_0x3  = 4;
038  public static final int AE_PATTERN_0x3D = 5;
039
040  private static final int FIELD0_OFFSET =
041    JavaHeader.objectStartOffset(RVMType.JavaLangObjectType) +
042    ObjectModel.computeScalarHeaderSize(RVMType.JavaLangObjectType);
043
044  private static final int FIELD1_OFFSET = FIELD0_OFFSET + BYTES_IN_ADDRESS;
045  private static final int FIELD2_OFFSET = FIELD1_OFFSET + BYTES_IN_ADDRESS;
046  private static final int FIELD3_OFFSET = FIELD2_OFFSET + BYTES_IN_ADDRESS;
047  private static final int FIELD4_OFFSET = FIELD3_OFFSET + BYTES_IN_ADDRESS;
048  private static final int FIELD5_OFFSET = FIELD4_OFFSET + BYTES_IN_ADDRESS;
049
050  /** Master switch */
051  public static final boolean ENABLED = true;
052
053  public static int referenceArray() {
054    if (!ENABLED)
055      return AlignmentEncoding.ALIGN_CODE_NONE;
056    return AE_REFARRAY;
057  }
058
059  public static int primitiveArray() {
060    if (!ENABLED)
061      return AlignmentEncoding.ALIGN_CODE_NONE;
062    return AE_PATTERN_0x0;
063  }
064
065  public static int fallback() {
066    if (!ENABLED)
067      return AlignmentEncoding.ALIGN_CODE_NONE;
068    return AE_FALLBACK;
069  }
070
071  public static int scalar(int[] offsets) {
072    if (!ENABLED)
073      return AlignmentEncoding.ALIGN_CODE_NONE;
074    if (offsets.length == 0) {
075      return AE_PATTERN_0x0;
076    }
077    if (offsets.length == 1) {
078      if (offsets[0] == FIELD0_OFFSET)
079        return AE_PATTERN_0x1;
080    }
081//    if (offsets.length == 2) {
082//      if (offsets[0] == FIELD0_OFFSET &&
083//          offsets[1] == FIELD1_OFFSET)
084//        return AE_PATTERN_0x3;
085//    }
086    if (offsets.length == 3) {
087      if (offsets[0] == FIELD0_OFFSET &&
088          offsets[1] == FIELD1_OFFSET &&
089          offsets[2] == FIELD2_OFFSET)
090        return AE_PATTERN_0x7;
091    }
092//    if (offsets.length == 5) {
093//      if (offsets[0] == FIELD0_OFFSET &&
094//          offsets[1] == FIELD2_OFFSET &&
095//          offsets[2] == FIELD3_OFFSET &&
096//          offsets[3] == FIELD4_OFFSET &&
097//          offsets[4] == FIELD5_OFFSET)
098//        return AE_PATTERN_0x3D;
099//    }
100    if (offsets.length == 6) {
101      if (offsets[0] == FIELD0_OFFSET &&
102          offsets[1] == FIELD1_OFFSET &&
103          offsets[2] == FIELD2_OFFSET &&
104          offsets[3] == FIELD3_OFFSET &&
105          offsets[4] == FIELD4_OFFSET &&
106          offsets[5] == FIELD5_OFFSET)
107        return AE_PATTERN_0x3F;
108    }
109    return AE_FALLBACK;
110  }
111
112  /**
113   * Hand-inlined scanning of objects.  The cases of the conditional
114   * are ordered in descending frequency of patterns.
115   *
116   * This entry point falls back to specialized scanning if it is enabled.
117   *
118   * @param code the code to use for specialized scanning. This determines
119   *  the pattern that will be used.
120   * @param id the id of the specialized scan method
121   * @param object the object to scan
122   * @param trace the closure to use
123   */
124  @Inline
125  @Uninterruptible
126  public static void scanObject(int code, int id, Object object, TransitiveClosure trace) {
127    scanObject(code, id, object, trace, SpecializedScanMethod.ENABLED);
128  }
129
130  /**
131   * Hand-inlined scanning of objects.  The cases of the conditional
132   * are ordered in descending frequency of patterns.
133   * <p>
134   * This entry point does not fall back to specialized scanning.
135   *
136   * @param code the code to use for specialized scanning. This determines
137   *  the pattern that will be used.
138   * @param object the object to scan
139   * @param trace the closure to use
140   */
141  @Inline
142  @Uninterruptible
143  public static void scanObject(int code, Object object, TransitiveClosure trace) {
144    scanObject(code, 0, object, trace, false);
145  }
146
147  @Inline
148  @Uninterruptible
149  private static void scanObject(int code, int id, Object object, TransitiveClosure trace, boolean specialize) {
150    if (code == AE_PATTERN_0x0) {
151      ;
152    } else if (code == AE_PATTERN_0x1) {
153      SpecializedScanMethod.pattern(0x1,object,trace);
154    } else if (code == AE_PATTERN_0x7) {
155      SpecializedScanMethod.pattern(0x7,object,trace);
156    } else if (code == AE_PATTERN_0x3F) {
157      SpecializedScanMethod.pattern(0x3F,object,trace);
158    } else if (code == AE_FALLBACK)  {
159      if (specialize)  {
160        SpecializedScanMethod.invoke(id, object,trace);
161      } else {
162        SpecializedScanMethod.fallback(object, trace);
163      }
164    } else if (code == AE_REFARRAY) {
165      SpecializedScanMethod.referenceArray(object,trace);
166    }  else if (code == AE_PATTERN_0x3) {
167      SpecializedScanMethod.pattern(0x3,object,trace);
168    } else if (code == AE_PATTERN_0x3D) {
169      SpecializedScanMethod.pattern(0x3D,object,trace);
170    }
171  }
172}