001/* 002 * BioJava development code 003 * 004 * This code may be freely distributed and modified under the 005 * terms of the GNU Lesser General Public Licence. This should 006 * be distributed with the code. If you do not have a copy, 007 * see: 008 * 009 * http://www.gnu.org/copyleft/lesser.html 010 * 011 * Copyright for this code is held jointly by the individual 012 * authors. These should be listed in @author doc comments. 013 * 014 * For more information on the BioJava project and its aims, 015 * or to join the biojava-l mailing list, visit the home page 016 * at: 017 * 018 * http://www.biojava.org/ 019 * 020 */ 021package org.biojava.utils.bytecode; 022 023import java.util.*; 024 025/** 026 * A list of Instructions and/or other CodeGenerator objects. 027 * 028 * @author Thomas Down 029 * @author Matthew Pocock 030 */ 031 032public class InstructionVector implements CodeGenerator { 033 private final List instructions; 034 private final Label startLabel; 035 private final Label endLabel; 036 037 private StatsCache statsCache; // gets set to null on edits 038 039 { 040 instructions = new ArrayList(); 041 startLabel = new Label(); 042 endLabel = new Label(); 043 statsCache = null; 044 } 045 046 public void add(CodeGenerator g) { 047 statsCache = null; 048 instructions.add(g); 049 } 050 051 public int size() { 052 return instructions.size(); 053 } 054 055 public void add(int pos, CodeGenerator g) { 056 statsCache = null; 057 instructions.add(pos, g); 058 } 059 060 public void remove(int pos) { 061 statsCache = null; 062 instructions.remove(pos); 063 } 064 065 public CodeGenerator generatorAt(int pos) { 066 return (CodeGenerator) instructions.get(pos); 067 } 068 069 public Label getStartLabel() { 070 return startLabel; 071 } 072 073 public Label getEndLabel() { 074 return endLabel; 075 } 076 077 public void writeCode(CodeContext ctx) throws CodeException { 078 CodeContext subctx = ctx.subContext(); 079 subctx.open(); 080 subctx.markLabel(startLabel); 081 for (Iterator i = instructions.iterator(); i.hasNext(); ) { 082 CodeGenerator cg = (CodeGenerator) i.next(); 083 cg.writeCode(subctx); 084 } 085 subctx.markLabel(endLabel); 086 subctx.close(); // Wrap up the subcontt 087 } 088 089 public int stackDepth() { 090 StatsCache statsCache = getStatsCache(); 091 092 return statsCache.depth; 093 } 094 095 public int stackDelta() { 096 StatsCache statsCache = getStatsCache(); 097 098 return statsCache.delta; 099 } 100 101 private StatsCache getStatsCache() { 102 if(statsCache == null) { 103 int depth = 0; 104 int delta = 0; 105 106 for(Iterator i = instructions.iterator(); i.hasNext(); ) { 107 CodeGenerator cg = (CodeGenerator) i.next(); 108 int dp = cg.stackDepth(); 109 int dl = cg.stackDelta(); 110 111 dp += delta; 112 delta += dl; 113 114 depth = Math.max(depth, dp); 115 } 116 117 statsCache = new StatsCache(depth, delta); 118 } 119 120 return statsCache; 121 } 122 123 private static class StatsCache { 124 public final int depth; 125 public final int delta; 126 127 public StatsCache(int depth, int delta) { 128 this.depth = depth; 129 this.delta = delta; 130 } 131 } 132}