
soot.asm.StackFrame Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of soot Show documentation
Show all versions of soot Show documentation
A Java Optimization Framework
package soot.asm;
/*-
* #%L
* Soot - a J*va Optimization Framework
* %%
* Copyright (C) 1997 - 2014 Raja Vallee-Rai and others
* %%
* This program 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 2.1 of the
* License, or (at your option) any later version.
*
* This program 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 General Lesser Public License for more details.
*
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* .
* #L%
*/
import java.util.ArrayList;
import soot.Local;
import soot.Unit;
import soot.ValueBox;
import soot.jimple.AssignStmt;
import soot.jimple.DefinitionStmt;
import soot.jimple.Jimple;
/**
* Frame of stack for an instruction.
*
* @author Aaloan Miftah
*/
final class StackFrame {
private Operand[] out;
private Local[] inStackLocals;
private ValueBox[] boxes;
private ArrayList in;
private final AsmMethodSource src;
/**
* Constructs a new stack frame.
*
* @param src
* source the frame belongs to.
*/
StackFrame(AsmMethodSource src) {
this.src = src;
}
/**
* @return operands produced by this frame.
*/
Operand[] out() {
return out;
}
/**
* Sets the operands used by this frame.
*
* @param oprs
* the operands.
*/
void in(Operand... oprs) {
ArrayList in = this.in;
if (in == null) {
in = this.in = new ArrayList(1);
} else {
in.clear();
}
in.add(oprs);
inStackLocals = new Local[oprs.length];
}
/**
* Sets the value boxes corresponding to the operands used by this frame.
*
* @param boxes
* the boxes.
*/
void boxes(ValueBox... boxes) {
this.boxes = boxes;
}
/**
* Sets the operands produced by this frame.
*
* @param oprs
* the operands.
*/
void out(Operand... oprs) {
out = oprs;
}
/**
* Merges the specified operands with the operands used by this frame.
*
* @param oprs
* the new operands.
* @throws IllegalArgumentException
* if the number of new operands is not equal to the number of old operands.
*/
void mergeIn(Operand... oprs) {
ArrayList in = this.in;
if (in.get(0).length != oprs.length) {
throw new IllegalArgumentException("Invalid in operands length!");
}
int nrIn = in.size();
boolean diff = false;
for (int i = 0; i != oprs.length; i++) {
Operand newOp = oprs[i];
diff = true;
/* merge, since prevOp != newOp */
Local stack = inStackLocals[i];
if (stack != null) {
if (newOp.stack == null) {
newOp.stack = stack;
AssignStmt as = Jimple.v().newAssignStmt(stack, newOp.value);
src.setUnit(newOp.insn, as);
newOp.updateBoxes();
} else {
AssignStmt as = Jimple.v().newAssignStmt(stack, newOp.stackOrValue());
src.mergeUnits(newOp.insn, as);
newOp.addBox(as.getRightOpBox());
}
} else {
for (int j = 0; j != nrIn; j++) {
stack = in.get(j)[i].stack;
if (stack != null) {
break;
}
}
if (stack == null) {
stack = newOp.stack;
if (stack == null) {
stack = src.newStackLocal();
}
}
/* add assign statement for prevOp */
ValueBox box = boxes == null ? null : boxes[i];
for (int j = 0; j != nrIn; j++) {
Operand prevOp = in.get(j)[i];
if (prevOp.stack == stack) {
continue;
}
prevOp.removeBox(box);
if (prevOp.stack == null) {
prevOp.stack = stack;
AssignStmt as = Jimple.v().newAssignStmt(stack, prevOp.value);
src.setUnit(prevOp.insn, as);
} else {
Unit u = src.getUnit(prevOp.insn);
DefinitionStmt as = (DefinitionStmt) (u instanceof UnitContainer ? ((UnitContainer) u).getFirstUnit() : u);
ValueBox lvb = as.getLeftOpBox();
assert lvb.getValue() == prevOp.stack : "Invalid stack local!";
lvb.setValue(stack);
prevOp.stack = stack;
}
prevOp.updateBoxes();
}
if (newOp.stack != stack) {
if (newOp.stack == null) {
newOp.stack = stack;
AssignStmt as = Jimple.v().newAssignStmt(stack, newOp.value);
src.setUnit(newOp.insn, as);
} else {
Unit u = src.getUnit(newOp.insn);
DefinitionStmt as = (DefinitionStmt) (u instanceof UnitContainer ? ((UnitContainer) u).getFirstUnit() : u);
ValueBox lvb = as.getLeftOpBox();
assert lvb.getValue() == newOp.stack : "Invalid stack local!";
lvb.setValue(stack);
newOp.stack = stack;
}
newOp.updateBoxes();
}
if (box != null) {
box.setValue(stack);
}
inStackLocals[i] = stack;
}
/*
* this version uses allocates local if it finds both operands have stack locals allocated already
*/
/*
* if (stack == null) { if (in.size() != 1) throw new AssertionError("Local h " + in.size()); stack =
* src.newStackLocal(); inStackLocals[i] = stack; ValueBox box = boxes == null ? null : boxes[i]; /* add assign
* statement for prevOp * for (int j = 0; j != nrIn; j++) { Operand prevOp = in.get(j)[i]; prevOp.removeBox(box); if
* (prevOp.stack == null) { prevOp.stack = stack; as = Jimple.v().newAssignStmt(stack, prevOp.value);
* src.setUnit(prevOp.insn, as); prevOp.updateBoxes(); } else { as = Jimple.v().newAssignStmt(stack,
* prevOp.stackOrValue()); src.mergeUnits(prevOp.insn, as); } prevOp.addBox(as.getRightOpBox()); } if (box != null)
* box.setValue(stack); } if (newOp.stack == null) { newOp.stack = stack; as = Jimple.v().newAssignStmt(stack,
* newOp.value); src.setUnit(newOp.insn, as); newOp.updateBoxes(); } else { as = Jimple.v().newAssignStmt(stack,
* newOp.stackOrValue()); src.mergeUnits(newOp.insn, as); } newOp.addBox(as.getRightOpBox());
*/
}
if (diff) {
in.add(oprs);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy