Package bytecodeparser.analysis.decoders

Source Code of bytecodeparser.analysis.decoders.DecodedLocalVariableOp

/*
*  Copyright (C) 2011 Stephane Godbillon
*  This file is part of BytecodeParser. See the README file in the root
*  directory of this project.
*
*  BytecodeParser is free software: you can redistribute it and/or modify
*  it under the terms of the GNU Lesser General Public License as published by
*  the Free Software Foundation, either version 3 of the License, or
*  (at your option) any later version.

*  BytecodeParser is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU Lesser General Public License for more details.

*  You should have received a copy of the GNU Lesser General Public License
*  along with BytecodeParser.  If not, see <http://www.gnu.org/licenses/>.
*/
package bytecodeparser.analysis.decoders;

import javassist.bytecode.Opcode;

import org.apache.log4j.Logger;

import bytecodeparser.Context;
import bytecodeparser.analysis.Opcodes.OpParameterType;
import static bytecodeparser.analysis.Opcodes.OpParameterType.*;
import bytecodeparser.analysis.LocalVariable;
import bytecodeparser.analysis.opcodes.LocalVariableOpcode;
import bytecodeparser.analysis.stack.Stack;
import bytecodeparser.analysis.stack.StackElement;
import bytecodeparser.analysis.stack.ValueFromLocalVariable;

/**
* A decoded local variable operation op.
* @author Stephane Godbillon
*
*/
public class DecodedLocalVariableOp extends DecodedOp {
  private static final Logger LOGGER = Logger.getLogger(DecodedLocalVariableOp.class);
  /**
   * The matching local variable.
   */
  public final LocalVariable localVariable;
  /**
   * States if this op is a read (load) or write (store).
   */
  public final boolean load;
  /**
   * States if the matching localVariable is one- or two-words long.
   */
  public final boolean doubleLength;
  /**
   * States if the op is wide (nb localvars > 256)
   */
  public final boolean isWide;
 
  public DecodedLocalVariableOp(LocalVariableOpcode lvo, Context context, int index, boolean isWide) {
    super(lvo, context, index, guessTypes(lvo, context, index, isWide), decodeValues(guessTypes(lvo, context, index, isWide), context.iterator, index + (isWide ? 1 : 0)));
    this.isWide = isWide;
    int slot;
    if(parameterTypes.length > 0)
      slot = parameterValues[0];
    else slot = lvo.getCode() - lvo.getBaseOpcode();
    localVariable = LocalVariable.getLocalVariable(slot, index, context.localVariables);
    int base = lvo.getBaseOpcode();
    this.load = lvo.isLoad();
    doubleLength = base == Opcode.DLOAD || base == Opcode.DLOAD_0 || base == Opcode.LLOAD || base == Opcode.LLOAD_0 || base == Opcode.DSTORE || base == Opcode.DSTORE_0 || base == Opcode.LSTORE || base == Opcode.LSTORE_0;
  }
 
  @Override
  public void simulate(Stack stack) {
    if(op.code != Opcode.IINC) {
      ValueFromLocalVariable toPush = new ValueFromLocalVariable(localVariable);
      if(!load) {
        StackElement poppedSe;
        if(doubleLength)
          poppedSe = stack.pop2();
        else poppedSe = stack.pop();
        /* when a name is null while LocalVariableTable is present, it is likely that this class has been
         * previously enhanced and this local variable is just a variable proxy, so grab the original local
         * variable and consider its name
         */
        if(poppedSe instanceof ValueFromLocalVariable && (localVariable == null || localVariable.name == null)) {
          LOGGER.debug("ATTENTION ************** variable proxy for lv = '" + ((ValueFromLocalVariable) poppedSe).localVariable + "'");
          toPush = new ValueFromLocalVariable(((ValueFromLocalVariable) poppedSe).localVariable);
        }
      } else {
        if(doubleLength)
          stack.push2(toPush);
        else stack.push(toPush);
      }
    }
  }
 
  private static OpParameterType[] guessTypes(LocalVariableOpcode lvo, Context context, int index, boolean isWide) {
    int code = lvo.code;
    if(code != Opcode.ALOAD &&
        code != Opcode.ASTORE &&
        code != Opcode.DLOAD &&
        code != Opcode.DSTORE &&
        code != Opcode.FLOAD &&
        code != Opcode.FSTORE &&
        code != Opcode.ILOAD &&
        code != Opcode.ISTORE &&
        code != Opcode.LLOAD &&
        code != Opcode.LSTORE &&
        code != Opcode.IINC)
      return new OpParameterType[0];
    boolean isIINC = lvo.code == Opcode.IINC;
    OpParameterType[] result = new OpParameterType[isIINC ? 2 : 1];
    result[0] = isWide ? U2 : U1;
    if(isIINC)
      result[1] = isWide ? S2 : S1;
    return result;
  }
}
TOP

Related Classes of bytecodeparser.analysis.decoders.DecodedLocalVariableOp

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.