All Downloads are FREE. Search and download functionalities are using the official Maven repository.

proguard.analysis.cpa.jvm.state.JvmFrameAbstractState Maven / Gradle / Ivy

Go to download

ProGuardCORE is a free library to read, analyze, modify, and write Java class files.

There is a newer version: 9.1.6
Show newest version
/*
 * 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