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.compilers.opt.bc2ir;
014    
015    import org.jikesrvm.compilers.opt.inlining.InlineSequence;
016    import org.jikesrvm.compilers.opt.ir.BasicBlock;
017    import org.jikesrvm.compilers.opt.ir.ControlFlowGraph;
018    import 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     */
024    class 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 (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() { flags |= STACK_KNOWN; }
070    
071      final void clearStackKnown() { flags &= ~STACK_KNOWN; }
072    
073      final boolean isStackKnown() { return (flags & STACK_KNOWN) != 0; }
074    
075      final void setLocalKnown() { flags |= LOCAL_KNOWN; }
076    
077      final void clearLocalKnown() { flags &= ~LOCAL_KNOWN; }
078    
079      final boolean isLocalKnown() { return (flags & LOCAL_KNOWN) != 0; }
080    
081      final void setSelfRegen() { flags |= SELF_REGEN; }
082    
083      final void clearSelfRegen() { flags &= ~SELF_REGEN; }
084    
085      final boolean isSelfRegen() { return (flags & SELF_REGEN) != 0; }
086    
087      final void setGenerated() { flags |= GENERATED; }
088    
089      final void clearGenerated() { flags &= ~GENERATED; }
090    
091      final boolean isGenerated() { return (flags & GENERATED) != 0; }
092    
093      final void setBlack() { flags |= COLOR; }
094    
095      final boolean isBlack() { return (flags & COLOR) != 0; }
096    
097      final void setRed() { flags &= ~COLOR; }
098    
099      final boolean isRed() { return (flags & COLOR) == 0; }
100    
101      final void setInCodeOrder() { flags |= IN_CODE_ORDER; }
102    
103      final void clearInCodeOrder() { flags &= ~IN_CODE_ORDER; }
104    
105      final boolean isInCodeOrder() { return (flags & IN_CODE_ORDER) != 0; }
106    
107      /**
108       * Is the BBLE ready to generate?
109       */
110      final boolean isReadyToGenerate() {
111        // (isStackKnown() && isLocalKnown && !isGenerated)
112        byte READY_MASK = STACK_KNOWN | LOCAL_KNOWN | GENERATED;
113        byte READY_VAL = STACK_KNOWN | LOCAL_KNOWN;
114        return (flags & READY_MASK) == READY_VAL;
115      }
116    
117      /**
118       * Save a shallow copy of the given local variable state into this.
119       * @param _localState local variable state to save
120       */
121      final void copyIntoLocalState(Operand[] _localState) {
122        localState = new Operand[_localState.length];
123        System.arraycopy(_localState, 0, localState, 0, _localState.length);
124        setLocalKnown();
125      }
126    
127      /**
128       * Return a shallow copy of my local state.
129       */
130      final Operand[] copyLocalState() {
131        Operand[] ls = new Operand[localState.length];
132        System.arraycopy(localState, 0, ls, 0, localState.length);
133        return ls;
134      }
135    
136      /**
137       * Add an exception handler BBLE to the handlers array.
138       * NOTE: this isn't incredibly efficient, but empirically the expected
139       * number of handlers per basic block is 0, with an observed
140       * maximum across 10,000+ methods of 3.
141       * Until this changes, we just don't care.
142       */
143      final void addHandler(HandlerBlockLE handler) {
144        if (handlers == null) {
145          handlers = new HandlerBlockLE[1];
146          handlers[0] = handler;
147        } else {
148          for (HandlerBlockLE handler1 : handlers) {
149            if (handler1 == handler) {
150              return;             //already there (was in emap more than once)
151            }
152          }
153          int n = handlers.length;
154          HandlerBlockLE[] tmp = new HandlerBlockLE[n + 1];
155          for (int i = 0; i < n; i++) {
156            tmp[i] = handlers[i];
157          }
158          tmp[n] = handler;
159          handlers = tmp;
160        }
161      }
162    
163      /**
164       * Create a new BBLE (and basic block) for the specified bytecode index.
165       *
166       * @param loc bytecode index
167       * @param position the inline sequence
168       * @param cfg ControlFlowGraph into which the block
169       *            will eventually be inserted
170       */
171      BasicBlockLE(int loc, InlineSequence position, ControlFlowGraph cfg) {
172        block = new BasicBlock(loc, position, cfg);
173        low = loc;
174        high = loc;
175      }
176    
177      // Only for use by subclasses to avoid above constructor.
178      protected BasicBlockLE(int loc) { low = loc;  }
179    
180      /**
181       * Returns a string representation of this BBLE.
182       */
183      @Override
184      public String toString() {
185        if (isGenerated()) {
186          return "(" + low + "," + high + "," + max + ")";
187        }
188        if (isReadyToGenerate()) {
189          return "{" + low + "," + max + "}";
190        }
191        return "[" + low + "," + max + "]";
192      }
193    
194      /**
195       * Returns a string representation of state that determines if the BBLE
196       * is ready to be generated */
197      public String genState() {
198        return "(sk=" + isStackKnown() + ", lk=" + isLocalKnown() + ", gen=" + isGenerated() + ")";
199      }
200    }