proguard.analysis.cpa.jvm.state.JvmFrameAbstractState Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of proguard-core Show documentation
Show all versions of proguard-core Show documentation
ProGuardCORE is a free library to read, analyze, modify, and write Java class files.
/*
* ProGuardCORE -- library to process Java bytecode.
*
* Copyright (c) 2002-2022 Guardsquare NV
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package proguard.analysis.cpa.jvm.state;
import java.util.List;
import java.util.Objects;
import proguard.analysis.cpa.defaults.LatticeAbstractState;
import proguard.analysis.cpa.defaults.ListAbstractState;
import proguard.analysis.cpa.defaults.StackAbstractState;
/**
* The {@link JvmFrameAbstractState} combines the operand stack as the {@link StackAbstractState}
* and the local variable array as the {@link ListAbstractState}. This abstract state does not
* restrict the way one models values, i.e., one abstract state may correspond to a byte sequence of
* arbitrary length.
*
* @author Dmitry Ivanov
*/
public class JvmFrameAbstractState>
implements LatticeAbstractState> {
protected final ListAbstractState localVariables;
protected final StackAbstractState operandStack;
/** Create an empty frame. */
public JvmFrameAbstractState() {
this(new ListAbstractState<>(), new StackAbstractState<>());
}
/**
* Create a frame from a local variable array and an operand stack.
*
* @param localVariables a local variable array
* @param operandStack an operand stack
*/
public JvmFrameAbstractState(
ListAbstractState localVariables, StackAbstractState operandStack) {
this.localVariables = localVariables;
this.operandStack = operandStack;
}
// implementations for LatticeAbstractState
@Override
public JvmFrameAbstractState join(JvmFrameAbstractState abstractState) {
JvmFrameAbstractState answer =
new JvmFrameAbstractState<>(
localVariables.join(abstractState.localVariables),
operandStack.join(abstractState.operandStack));
return equals(answer) ? this : answer;
}
@Override
public boolean isLessOrEqual(JvmFrameAbstractState abstractState) {
return localVariables.isLessOrEqual(abstractState.localVariables)
&& operandStack.isLessOrEqual(abstractState.operandStack);
}
// implementations for AbstractState
@Override
public JvmFrameAbstractState copy() {
return new JvmFrameAbstractState<>(
(ListAbstractState) localVariables.copy(),
(StackAbstractState) operandStack.copy());
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof JvmFrameAbstractState)) {
return false;
}
JvmFrameAbstractState other = (JvmFrameAbstractState) obj;
return localVariables.equals(other.localVariables) && operandStack.equals(other.operandStack);
}
@Override
public int hashCode() {
return Objects.hash(localVariables, operandStack);
}
/**
* Returns the {@code index}th element from the top of the operand stack or returns {@code
* defaultState} if the stack does not have enough elements.
*/
public StateT peekOrDefault(int index, StateT defaultState) {
return operandStack.peekOrDefault(index, defaultState);
}
/** Returns the {@code index}th element from the top of the operand stack. */
public StateT peek(int index) {
return operandStack.peek(index);
}
/** Removes the top element of the operand stack end returns it. */
public StateT pop() {
return operandStack.pop();
}
/**
* Removes the top element of the operand stack end returns it. Returns {@code defaultState} if
* the stack is empty.
*/
public StateT popOrDefault(StateT defaultState) {
return operandStack.popOrDefault(defaultState);
}
/** Inserts {@code state} to the top of the operand stack and returns it. */
public StateT push(StateT state) {
return operandStack.push(state);
}
/**
* Sequentially inserts elements of {@code states} to the top of the operand stack and returns
* {@code states}.
*/
public List pushAll(List states) {
states.forEach(operandStack::push);
return states;
}
/**
* Returns an abstract state at the {@code index}th position of the variable array or {@code
* defaultState} if there is no entry.
*/
public StateT getVariableOrDefault(int index, StateT defaultState) {
return localVariables.getOrDefault(index, defaultState);
}
/**
* Sets the {@code index}th position of the variable array to {@code state} and returns {@code
* state}. If the array has to be extended, the added cells are padded with {@code defaultState}.
*/
public StateT setVariable(int index, StateT state, StateT defaultState) {
return localVariables.set(index, state, defaultState);
}
/** Returns the variable array. */
public ListAbstractState getLocalVariables() {
return localVariables;
}
/** Returns the operand stack. */
public StackAbstractState getOperandStack() {
return operandStack;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy