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.VM;
016import org.jikesrvm.compilers.opt.ir.operand.Operand;
017
018/**
019 * Simulates the Java stack for abstract interpretation in {@link BC2IR}.<p>
020 *
021 * This class is intended to be used by a single thread. Methods from this
022 * class do not provide any error handling.<p>
023 *
024 * The total amount of {@link Operand}s that can be accepted by an operand stack
025 * is called the capacity of the operand stack. It is determined when the stack is
026 * created. The capacity is distinct from the current number of operands on the stack
027 * which is called the size of the operand stack.
028 */
029final class OperandStack {
030
031  private final Operand[] stack;
032  private int top;
033
034  /**
035   * Creates an operand stack.
036   *
037   * @param capacity the maximum number of operands that the stack
038   *  must be able to hold, must be {@code >= 0}
039   */
040  OperandStack(int capacity) {
041    stack = new Operand[capacity];
042    top = 0;
043  }
044
045  void push(Operand val) {
046//    if (VM.VerifyAssertions) VM._assert(val.instruction == null);
047    stack[top++] = val;
048  }
049
050  Operand pop() {
051    return stack[--top];
052  }
053
054  /**
055   * Pops the two topmost operands from the stack and discards them.<p>
056   *
057   * This implements the pop2 bytecode.
058   */
059  void pop2() {
060    pop();
061    pop();
062  }
063
064  Operand getFromBottom(int pos) {
065    return stack[pos];
066  }
067
068  Operand getFromTop(int n) {
069    return stack[top - n - 1];
070  }
071
072  void replaceFromTop(int n, Operand op) {
073    if (VM.VerifyAssertions) VM._assert(op.instruction == null);
074    stack[top - n - 1] = op;
075  }
076
077  /**
078   * Swaps the two topmost operands on the stack.<p>
079   *
080   * This implements the swap bytecode.
081   */
082  void swap() {
083    Operand v1 = pop();
084    Operand v2 = pop();
085    push(v1);
086    push(v2);
087  }
088
089  void clear() {
090    top = 0;
091  }
092
093  /**
094   * Returns a deep copy of the stack.<p>
095   *
096   * The copied stack has copies of the operands from the original stack. The
097   * size and capacity of the copied stack are equal to the original stack
098   * at the time of the copy.
099   *
100   * @return a copy of the stack
101   */
102  OperandStack deepCopy() {
103    OperandStack newss = new OperandStack(stack.length);
104    newss.top = top;
105    for (int i = 0; i < top; i++) {
106      // deep copy of stack
107      newss.stack[i] = stack[i].copy();
108    }
109    return newss;
110  }
111
112  boolean isEmpty() {
113    return (top == 0);
114  }
115
116  /**
117   * Returns the current size of the stack.
118   *
119   * @return the current number of operands on the stack
120   */
121  int getSize() {
122    return top;
123  }
124
125  /**
126   * Returns a new, empty operand stack that has the same capacity
127   * as this one.
128   * @return a new operand stack
129   */
130  OperandStack createEmptyOperandStackWithSameCapacity() {
131    return new OperandStack(stack.length);
132  }
133
134
135}