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.compilers.opt.bc2ir;
014
015import org.jikesrvm.compilers.opt.inlining.InlineSequence;
016import org.jikesrvm.compilers.opt.ir.BasicBlock;
017import org.jikesrvm.compilers.opt.ir.ControlFlowGraph;
018import org.jikesrvm.compilers.opt.ir.operand.Operand;
019
020/**
021 * This class is used as a 'wrapper' to a basic block to hold
022 * information that is necessary only for IR generation.
023 */
024class BasicBlockLE {
025  // Used by BBSet to maintain red/black tree of BBLE's during generation
026  BasicBlockLE parent, left, right;
027
028  /** Start bytecode of this BBLE */
029  final int low;
030
031  /** Current end bytecode of this BBLE */
032  int high;
033
034  /** Maximum possible bytecode of this BBLE (wrt exception ranges) */
035  int max;
036
037  /** Basic block that this BBLE refers to. */
038  BasicBlock block;
039
040  /** State of the stack at the start of this basic block. */
041  OperandStack stackState;
042
043  /** State of the local variables at the start of this basic block. */
044  Operand[] localState;
045
046  /**
047   * The desired fallthrough (next in code order) BBLE (may be {@code null}).
048   * NOTE: we may not always end up actually falling through
049   * (see BBSet.finalPass).
050   */
051  BasicBlockLE fallThrough;
052
053  /**
054   * The exception handler BBLE's for this block ({@code null} if none)
055   */
056  HandlerBlockLE[] handlers;
057
058  /**
059   * Encoding of random boolean state
060   */
061  private byte flags;
062  private static final byte STACK_KNOWN = 0x01;
063  private static final byte LOCAL_KNOWN = 0x02;
064  private static final byte SELF_REGEN = 0x04;
065  private static final byte GENERATED = 0x08;
066  private static final byte COLOR = 0x10;           //(Red = 0, Black = 1)
067  private static final byte IN_CODE_ORDER = 0x20;
068
069  final void setStackKnown() {
070    flags |= STACK_KNOWN;
071  }
072
073  final void clearStackKnown() {
074    flags &= ~STACK_KNOWN;
075  }
076
077  final boolean isStackKnown() {
078    return (flags & STACK_KNOWN) != 0;
079  }
080
081  final void setLocalKnown() {
082    flags |= LOCAL_KNOWN;
083  }
084
085  final void clearLocalKnown() {
086    flags &= ~LOCAL_KNOWN;
087  }
088
089  final boolean isLocalKnown() {
090    return (flags & LOCAL_KNOWN) != 0;
091  }
092
093  final void setSelfRegen() {
094    flags |= SELF_REGEN;
095  }
096
097  final void clearSelfRegen() {
098    flags &= ~SELF_REGEN;
099  }
100
101  final boolean isSelfRegen() {
102    return (flags & SELF_REGEN) != 0;
103  }
104
105  final void setGenerated() {
106    flags |= GENERATED;
107  }
108
109  final void clearGenerated() {
110    flags &= ~GENERATED;
111  }
112
113  final boolean isGenerated() {
114    return (flags & GENERATED) != 0;
115  }
116
117  final void setBlack() {
118    flags |= COLOR;
119  }
120
121  final boolean isBlack() {
122    return (flags & COLOR) != 0;
123  }
124
125  final void setRed() {
126    flags &= ~COLOR;
127  }
128
129  final boolean isRed() {
130    return (flags & COLOR) == 0;
131  }
132
133  final void setInCodeOrder() {
134    flags |= IN_CODE_ORDER;
135  }
136
137  final void clearInCodeOrder() {
138    flags &= ~IN_CODE_ORDER;
139  }
140
141  final boolean isInCodeOrder() {
142    return (flags & IN_CODE_ORDER) != 0;
143  }
144
145  final boolean isReadyToGenerate() {
146    // (isStackKnown() && isLocalKnown && !isGenerated)
147    byte READY_MASK = STACK_KNOWN | LOCAL_KNOWN | GENERATED;
148    byte READY_VAL = STACK_KNOWN | LOCAL_KNOWN;
149    return (flags & READY_MASK) == READY_VAL;
150  }
151
152  /**
153   * Save a shallow copy of the given local variable state into this.
154   * @param _localState local variable state to save
155   */
156  final void copyIntoLocalState(Operand[] _localState) {
157    localState = new Operand[_localState.length];
158    System.arraycopy(_localState, 0, localState, 0, _localState.length);
159    setLocalKnown();
160  }
161
162  /**
163   * @return a shallow copy of the local state
164   */
165  final Operand[] copyLocalState() {
166    Operand[] ls = new Operand[localState.length];
167    System.arraycopy(localState, 0, ls, 0, localState.length);
168    return ls;
169  }
170
171  /**
172   * Adds an exception handler BBLE to the handlers array.
173   * <p>
174   * NOTE: this isn't incredibly efficient, but empirically the expected
175   * number of handlers per basic block is 0, with an observed
176   * maximum across 10,000+ methods of 3.
177   * Until this changes, we just don't care.
178   *
179   * @param handler the handler block to add
180   */
181  final void addHandler(HandlerBlockLE handler) {
182    if (handlers == null) {
183      handlers = new HandlerBlockLE[1];
184      handlers[0] = handler;
185    } else {
186      for (HandlerBlockLE handler1 : handlers) {
187        if (handler1 == handler) {
188          return;             //already there (was in emap more than once)
189        }
190      }
191      int n = handlers.length;
192      HandlerBlockLE[] tmp = new HandlerBlockLE[n + 1];
193      for (int i = 0; i < n; i++) {
194        tmp[i] = handlers[i];
195      }
196      tmp[n] = handler;
197      handlers = tmp;
198    }
199  }
200
201  /**
202   * Create a new BBLE (and basic block) for the specified bytecode index.
203   *
204   * @param loc bytecode index
205   * @param position the inline sequence
206   * @param cfg ControlFlowGraph into which the block
207   *            will eventually be inserted
208   */
209  BasicBlockLE(int loc, InlineSequence position, ControlFlowGraph cfg) {
210    block = new BasicBlock(loc, position, cfg);
211    low = loc;
212    high = loc;
213  }
214
215  // Only for use by subclasses to avoid above constructor.
216  protected BasicBlockLE(int loc) {
217    low = loc;
218  }
219
220  /**
221   * Returns a string representation of this BBLE.
222   */
223  @Override
224  public String toString() {
225    if (isGenerated()) {
226      return "(" + low + "," + high + "," + max + ")";
227    }
228    if (isReadyToGenerate()) {
229      return "{" + low + "," + max + "}";
230    }
231    return "[" + low + "," + max + "]";
232  }
233
234  /**
235   * @return a string representation of state that determines if the BBLE
236   * is ready to be generated
237   */
238  public String genState() {
239    return "(sk=" + isStackKnown() + ", lk=" + isLocalKnown() + ", gen=" + isGenerated() + ")";
240  }
241}