/** * Write the local variable table. The necessary constants have already been added to the constant * table by the collect() method. The flowFields method is used to determine which variables are * alive at each pc. */ public void writeLocalVariableTable( Environment env, MemberDefinition field, DataOutputStream out, ConstantPool tab) throws IOException { MemberDefinition locals[] = new MemberDefinition[maxvar]; int i = 0; // Initialize arguments if ((field != null) && (field.getArguments() != null)) { int reg = 0; Vector v = field.getArguments(); for (Enumeration e = v.elements(); e.hasMoreElements(); ) { MemberDefinition f = ((MemberDefinition) e.nextElement()); locals[reg] = f; reg += f.getType().stackSize(); } } flowFields(env, first, locals); LocalVariableTable lvtab = new LocalVariableTable(); // Initialize arguments again for (i = 0; i < maxvar; i++) locals[i] = null; if ((field != null) && (field.getArguments() != null)) { int reg = 0; Vector v = field.getArguments(); for (Enumeration e = v.elements(); e.hasMoreElements(); ) { MemberDefinition f = ((MemberDefinition) e.nextElement()); locals[reg] = f; lvtab.define(f, reg, 0, maxpc); reg += f.getType().stackSize(); } } int pcs[] = new int[maxvar]; for (Instruction inst = first; inst != null; inst = inst.next) { switch (inst.opc) { case opc_istore: case opc_istore_0: case opc_istore_1: case opc_istore_2: case opc_istore_3: case opc_fstore: case opc_fstore_0: case opc_fstore_1: case opc_fstore_2: case opc_fstore_3: case opc_astore: case opc_astore_0: case opc_astore_1: case opc_astore_2: case opc_astore_3: case opc_lstore: case opc_lstore_0: case opc_lstore_1: case opc_lstore_2: case opc_lstore_3: case opc_dstore: case opc_dstore_0: case opc_dstore_1: case opc_dstore_2: case opc_dstore_3: if (inst.value instanceof LocalVariable) { LocalVariable v = (LocalVariable) inst.value; int pc = (inst.next != null) ? inst.next.pc : inst.pc; if (locals[v.slot] != null) { lvtab.define(locals[v.slot], v.slot, pcs[v.slot], pc); } pcs[v.slot] = pc; locals[v.slot] = v.field; } break; case opc_label: { // flush previous labels for (i = 0; i < maxvar; i++) { if (locals[i] != null) { lvtab.define(locals[i], i, pcs[i], inst.pc); } } // init new labels int pc = inst.pc; MemberDefinition[] labelLocals = ((Label) inst).locals; if (labelLocals == null) { // unreachable code?? for (i = 0; i < maxvar; i++) locals[i] = null; } else { System.arraycopy(labelLocals, 0, locals, 0, maxvar); } for (i = 0; i < maxvar; i++) { pcs[i] = pc; } break; } } } // flush remaining labels for (i = 0; i < maxvar; i++) { if (locals[i] != null) { lvtab.define(locals[i], i, pcs[i], maxpc); } } // write the local variable table lvtab.write(env, out, tab); }
/** * Figure out when registers contain a legal value. This is done using a simple data flow * algorithm. This information is later used to generate the local variable table. */ void flowFields(Environment env, Label lbl, MemberDefinition locals[]) { if (lbl.locals != null) { // Been here before. Erase any conflicts. MemberDefinition f[] = lbl.locals; for (int i = 0; i < maxvar; i++) { if (f[i] != locals[i]) { f[i] = null; } } return; } // Remember the set of active registers at this point lbl.locals = new MemberDefinition[maxvar]; System.arraycopy(locals, 0, lbl.locals, 0, maxvar); MemberDefinition newlocals[] = new MemberDefinition[maxvar]; System.arraycopy(locals, 0, newlocals, 0, maxvar); locals = newlocals; for (Instruction inst = lbl.next; inst != null; inst = inst.next) { switch (inst.opc) { case opc_istore: case opc_istore_0: case opc_istore_1: case opc_istore_2: case opc_istore_3: case opc_fstore: case opc_fstore_0: case opc_fstore_1: case opc_fstore_2: case opc_fstore_3: case opc_astore: case opc_astore_0: case opc_astore_1: case opc_astore_2: case opc_astore_3: case opc_lstore: case opc_lstore_0: case opc_lstore_1: case opc_lstore_2: case opc_lstore_3: case opc_dstore: case opc_dstore_0: case opc_dstore_1: case opc_dstore_2: case opc_dstore_3: if (inst.value instanceof LocalVariable) { LocalVariable v = (LocalVariable) inst.value; locals[v.slot] = v.field; } break; case opc_label: flowFields(env, (Label) inst, locals); return; case opc_ifeq: case opc_ifne: case opc_ifgt: case opc_ifge: case opc_iflt: case opc_ifle: case opc_if_icmpeq: case opc_if_icmpne: case opc_if_icmpgt: case opc_if_icmpge: case opc_if_icmplt: case opc_if_icmple: case opc_if_acmpeq: case opc_if_acmpne: case opc_ifnull: case opc_ifnonnull: case opc_jsr: flowFields(env, (Label) inst.value, locals); break; case opc_goto: flowFields(env, (Label) inst.value, locals); return; case opc_return: case opc_ireturn: case opc_lreturn: case opc_freturn: case opc_dreturn: case opc_areturn: case opc_athrow: case opc_ret: return; case opc_tableswitch: case opc_lookupswitch: { SwitchData sw = (SwitchData) inst.value; flowFields(env, sw.defaultLabel, locals); for (Enumeration e = sw.tab.elements(); e.hasMoreElements(); ) { flowFields(env, (Label) e.nextElement(), locals); } return; } case opc_try: { Vector catches = ((TryData) inst.value).catches; for (Enumeration e = catches.elements(); e.hasMoreElements(); ) { CatchData cd = (CatchData) e.nextElement(); flowFields(env, cd.getLabel(), locals); } break; } } } }