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}