diff options
Diffstat (limited to 'src/main/javassist/bytecode/stackmap/Liveness.java')
-rw-r--r-- | src/main/javassist/bytecode/stackmap/Liveness.java | 365 |
1 files changed, 0 insertions, 365 deletions
diff --git a/src/main/javassist/bytecode/stackmap/Liveness.java b/src/main/javassist/bytecode/stackmap/Liveness.java deleted file mode 100644 index 4acd65e..0000000 --- a/src/main/javassist/bytecode/stackmap/Liveness.java +++ /dev/null @@ -1,365 +0,0 @@ -/* - * Javassist, a Java-bytecode translator toolkit. - * Copyright (C) 1999-2007 Shigeru Chiba. All Rights Reserved. - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. Alternatively, the contents of this file may be used under - * the terms of the GNU Lesser General Public License Version 2.1 or later. - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - */ - - package javassist.bytecode.stackmap; - -import javassist.bytecode.*; - -public class Liveness { - protected static final byte UNKNOWN = 0; - protected static final byte READ = 1; - protected static final byte UPDATED = 2; - protected byte[] localsUsage; - - /** - * If true, all the arguments become alive within the whole method body. - * - * To correctly compute a stack map table, all the arguments must - * be alive (localsUsage[?] must be READ) at least in the first block. - */ - public static boolean useArgs = true; - - public void compute(CodeIterator ci, TypedBlock[] blocks, int maxLocals, - TypeData[] args) - throws BadBytecode - { - computeUsage(ci, blocks, maxLocals); - if (useArgs) - useAllArgs(blocks, args); - - computeLiveness1(blocks[0]); - while (hasChanged(blocks)) - computeLiveness2(blocks[0]); - } - - private void useAllArgs(TypedBlock[] blocks, TypeData[] args) { - for (int k = 0; k < blocks.length; k++) { - byte[] usage = blocks[k].localsUsage; - for (int i = 0; i < args.length; i++) - if (args[i] != TypeTag.TOP) - usage[i] = READ; - } - } - - static final int NOT_YET = 0; - static final int CHANGED_LAST = 1; - static final int DONE = 2; - static final int CHANGED_NOW = 3; - - private void computeLiveness1(TypedBlock tb) { - if (tb.updating) { - // a loop was detected. - computeLiveness1u(tb); - return; - } - - if (tb.inputs != null) - return; - - tb.updating = true; - byte[] usage = tb.localsUsage; - int n = usage.length; - boolean[] in = new boolean[n]; - for (int i = 0; i < n; i++) - in[i] = usage[i] == READ; - - BasicBlock.Catch handlers = tb.toCatch; - while (handlers != null) { - TypedBlock h = (TypedBlock)handlers.body; - computeLiveness1(h); - for (int k = 0; k < n; k++) - if (h.inputs[k]) - in[k] = true; - - handlers = handlers.next; - } - - if (tb.exit != null) { - for (int i = 0; i < tb.exit.length; i++) { - TypedBlock e = (TypedBlock)tb.exit[i]; - computeLiveness1(e); - for (int k = 0; k < n; k++) - if (!in[k]) - in[k] = usage[k] == UNKNOWN && e.inputs[k]; - } - } - - tb.updating = false; - if (tb.inputs == null) { - tb.inputs = in; - tb.status = DONE; - } - else { - for (int i = 0; i < n; i++) - if (in[i] && !tb.inputs[i]) { - tb.inputs[i] = true; - tb.status = CHANGED_NOW; - } - } - } - - private void computeLiveness1u(TypedBlock tb) { - if (tb.inputs == null) { - byte[] usage = tb.localsUsage; - int n = usage.length; - boolean[] in = new boolean[n]; - for (int i = 0; i < n; i++) - in[i] = usage[i] == READ; - - tb.inputs = in; - tb.status = DONE; - } - } - - private void computeLiveness2(TypedBlock tb) { - if (tb.updating || tb.status >= DONE) - return; - - tb.updating = true; - if (tb.exit == null) - tb.status = DONE; - else { - boolean changed = false; - for (int i = 0; i < tb.exit.length; i++) { - TypedBlock e = (TypedBlock)tb.exit[i]; - computeLiveness2(e); - if (e.status != DONE) - changed = true; - } - - if (changed) { - changed = false; - byte[] usage = tb.localsUsage; - int n = usage.length; - for (int i = 0; i < tb.exit.length; i++) { - TypedBlock e = (TypedBlock)tb.exit[i]; - if (e.status != DONE) - for (int k = 0; k < n; k++) - if (!tb.inputs[k]) { - if (usage[k] == UNKNOWN && e.inputs[k]) { - tb.inputs[k] = true; - changed = true; - } - } - } - - tb.status = changed ? CHANGED_NOW : DONE; - } - else - tb.status = DONE; - } - - if (computeLiveness2except(tb)) - tb.status = CHANGED_NOW; - - tb.updating = false; - } - - private boolean computeLiveness2except(TypedBlock tb) { - BasicBlock.Catch handlers = tb.toCatch; - boolean changed = false; - while (handlers != null) { - TypedBlock h = (TypedBlock)handlers.body; - computeLiveness2(h); - if (h.status != DONE) { - boolean[] in = tb.inputs; - int n = in.length; - for (int k = 0; k < n; k++) - if (!in[k] && h.inputs[k]) { - in[k] = true; - changed = true; - } - } - - handlers = handlers.next; - } - - return changed; - } - - private boolean hasChanged(TypedBlock[] blocks) { - int n = blocks.length; - boolean changed = false; - for (int i = 0; i < n; i++) { - TypedBlock tb = blocks[i]; - if (tb.status == CHANGED_NOW) { - tb.status = CHANGED_LAST; - changed = true; - } - else - tb.status = NOT_YET; - } - - return changed; - } - - private void computeUsage(CodeIterator ci, TypedBlock[] blocks, int maxLocals) - throws BadBytecode - { - int n = blocks.length; - for (int i = 0; i < n; i++) { - TypedBlock tb = blocks[i]; - localsUsage = tb.localsUsage = new byte[maxLocals]; - int pos = tb.position; - analyze(ci, pos, pos + tb.length); - localsUsage = null; - } - } - - protected final void readLocal(int reg) { - if (localsUsage[reg] == UNKNOWN) - localsUsage[reg] = READ; - } - - protected final void writeLocal(int reg) { - if (localsUsage[reg] == UNKNOWN) - localsUsage[reg] = UPDATED; - } - - protected void analyze(CodeIterator ci, int begin, int end) - throws BadBytecode - { - ci.begin(); - ci.move(begin); - while (ci.hasNext()) { - int index = ci.next(); - if (index >= end) - break; - - int op = ci.byteAt(index); - if (op < 96) - if (op < 54) - doOpcode0_53(ci, index, op); - else - doOpcode54_95(ci, index, op); - else - if (op == Opcode.IINC) { - // this does not call writeLocal(). - readLocal(ci.byteAt(index + 1)); - } - else if (op == Opcode.WIDE) - doWIDE(ci, index); - } - } - - private void doOpcode0_53(CodeIterator ci, int pos, int op) { - switch (op) { - case Opcode.ILOAD : - case Opcode.LLOAD : - case Opcode.FLOAD : - case Opcode.DLOAD : - case Opcode.ALOAD : - readLocal(ci.byteAt(pos + 1)); - break; - case Opcode.ILOAD_0 : - case Opcode.ILOAD_1 : - case Opcode.ILOAD_2 : - case Opcode.ILOAD_3 : - readLocal(op - Opcode.ILOAD_0); - break; - case Opcode.LLOAD_0 : - case Opcode.LLOAD_1 : - case Opcode.LLOAD_2 : - case Opcode.LLOAD_3 : - readLocal(op - Opcode.LLOAD_0); - break; - case Opcode.FLOAD_0 : - case Opcode.FLOAD_1 : - case Opcode.FLOAD_2 : - case Opcode.FLOAD_3 : - readLocal(op - Opcode.FLOAD_0); - break; - case Opcode.DLOAD_0 : - case Opcode.DLOAD_1 : - case Opcode.DLOAD_2 : - case Opcode.DLOAD_3 : - readLocal(op - Opcode.DLOAD_0); - break; - case Opcode.ALOAD_0 : - case Opcode.ALOAD_1 : - case Opcode.ALOAD_2 : - case Opcode.ALOAD_3 : - readLocal(op - Opcode.ALOAD_0); - break; - } - } - - private void doOpcode54_95(CodeIterator ci, int pos, int op) { - switch (op) { - case Opcode.ISTORE : - case Opcode.LSTORE : - case Opcode.FSTORE : - case Opcode.DSTORE : - case Opcode.ASTORE : - writeLocal(ci.byteAt(pos + 1)); - break; - case Opcode.ISTORE_0 : - case Opcode.ISTORE_1 : - case Opcode.ISTORE_2 : - case Opcode.ISTORE_3 : - writeLocal(op - Opcode.ISTORE_0); - break; - case Opcode.LSTORE_0 : - case Opcode.LSTORE_1 : - case Opcode.LSTORE_2 : - case Opcode.LSTORE_3 : - writeLocal(op - Opcode.LSTORE_0); - break; - case Opcode.FSTORE_0 : - case Opcode.FSTORE_1 : - case Opcode.FSTORE_2 : - case Opcode.FSTORE_3 : - writeLocal(op - Opcode.FSTORE_0); - break; - case Opcode.DSTORE_0 : - case Opcode.DSTORE_1 : - case Opcode.DSTORE_2 : - case Opcode.DSTORE_3 : - writeLocal(op - Opcode.DSTORE_0); - break; - case Opcode.ASTORE_0 : - case Opcode.ASTORE_1 : - case Opcode.ASTORE_2 : - case Opcode.ASTORE_3 : - writeLocal(op - Opcode.ASTORE_0); - break; - } - } - - private void doWIDE(CodeIterator ci, int pos) throws BadBytecode { - int op = ci.byteAt(pos + 1); - int var = ci.u16bitAt(pos + 2); - switch (op) { - case Opcode.ILOAD : - case Opcode.LLOAD : - case Opcode.FLOAD : - case Opcode.DLOAD : - case Opcode.ALOAD : - readLocal(var); - break; - case Opcode.ISTORE : - case Opcode.LSTORE : - case Opcode.FSTORE : - case Opcode.DSTORE : - case Opcode.ASTORE : - writeLocal(var); - break; - case Opcode.IINC : - readLocal(var); - // this does not call writeLocal(). - break; - } - } -} |