Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/tools/asm/Assembler.java
38918 views
/*1* Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.tools.asm;2627import sun.tools.java.*;28import java.util.Enumeration;29import java.io.IOException;30import java.io.DataOutputStream;31import java.io.PrintStream;32import java.util.Vector;33// JCOV34import sun.tools.javac.*;35import java.io.File;36import java.io.BufferedInputStream;37import java.io.DataInputStream;38import java.io.FileInputStream;39import java.io.FileNotFoundException;40import java.io.FileOutputStream;41import java.lang.String;42// end JCOV4344/**45* This class is used to assemble the bytecode instructions for a method.46*47* WARNING: The contents of this source file are not part of any48* supported API. Code that depends on them does so at its own risk:49* they are subject to change or removal without notice.50*51* @author Arthur van Hoff52*/53public final54class Assembler implements Constants {55static final int NOTREACHED = 0;56static final int REACHED = 1;57static final int NEEDED = 2;5859Label first = new Label();60Instruction last = first;61int maxdepth;62int maxvar;63int maxpc;6465/**66* Add an instruction67*/68public void add(Instruction inst) {69if (inst != null) {70last.next = inst;71last = inst;72}73}74public void add(long where, int opc) {75add(new Instruction(where, opc, null));76}77public void add(long where, int opc, Object obj) {78add(new Instruction(where, opc, obj));79}80// JCOV81public void add(long where, int opc, Object obj, boolean flagCondInverted) {82add(new Instruction(where, opc, obj, flagCondInverted));83}8485public void add(boolean flagNoCovered, long where, int opc, Object obj) {86add(new Instruction(flagNoCovered, where, opc, obj));87}8889public void add(long where, int opc, boolean flagNoCovered) {90add(new Instruction(where, opc, flagNoCovered));91}9293static Vector<String> SourceClassList = new Vector<>();9495static Vector<String> TmpCovTable = new Vector<>();9697static int[] JcovClassCountArray = new int[CT_LAST_KIND + 1];9899static String JcovMagicLine = "JCOV-DATA-FILE-VERSION: 2.0";100static String JcovClassLine = "CLASS: ";101static String JcovSrcfileLine = "SRCFILE: ";102static String JcovTimestampLine = "TIMESTAMP: ";103static String JcovDataLine = "DATA: ";104static String JcovHeadingLine = "#kind\tcount";105106static int[] arrayModifiers =107{M_PUBLIC, M_PRIVATE, M_PROTECTED, M_ABSTRACT, M_FINAL, M_INTERFACE};108static int[] arrayModifiersOpc =109{PUBLIC, PRIVATE, PROTECTED, ABSTRACT, FINAL, INTERFACE};110//end JCOV111112/**113* Optimize instructions and mark those that can be reached114*/115void optimize(Environment env, Label lbl) {116lbl.pc = REACHED;117118for (Instruction inst = lbl.next ; inst != null ; inst = inst.next) {119switch (inst.pc) {120case NOTREACHED:121inst.optimize(env);122inst.pc = REACHED;123break;124case REACHED:125return;126case NEEDED:127break;128}129130switch (inst.opc) {131case opc_label:132case opc_dead:133if (inst.pc == REACHED) {134inst.pc = NOTREACHED;135}136break;137138case opc_ifeq:139case opc_ifne:140case opc_ifgt:141case opc_ifge:142case opc_iflt:143case opc_ifle:144case opc_if_icmpeq:145case opc_if_icmpne:146case opc_if_icmpgt:147case opc_if_icmpge:148case opc_if_icmplt:149case opc_if_icmple:150case opc_if_acmpeq:151case opc_if_acmpne:152case opc_ifnull:153case opc_ifnonnull:154optimize(env, (Label)inst.value);155break;156157case opc_goto:158optimize(env, (Label)inst.value);159return;160161case opc_jsr:162optimize(env, (Label)inst.value);163break;164165case opc_ret:166case opc_return:167case opc_ireturn:168case opc_lreturn:169case opc_freturn:170case opc_dreturn:171case opc_areturn:172case opc_athrow:173return;174175case opc_tableswitch:176case opc_lookupswitch: {177SwitchData sw = (SwitchData)inst.value;178optimize(env, sw.defaultLabel);179for (Enumeration<Label> e = sw.tab.elements() ; e.hasMoreElements();) {180optimize(env, e.nextElement());181}182return;183}184185case opc_try: {186TryData td = (TryData)inst.value;187td.getEndLabel().pc = NEEDED;188for (Enumeration<CatchData> e = td.catches.elements() ; e.hasMoreElements();) {189CatchData cd = e.nextElement();190optimize(env, cd.getLabel());191}192break;193}194}195}196}197198/**199* Eliminate instructions that are not reached200*/201boolean eliminate() {202boolean change = false;203Instruction prev = first;204205for (Instruction inst = first.next ; inst != null ; inst = inst.next) {206if (inst.pc != NOTREACHED) {207prev.next = inst;208prev = inst;209inst.pc = NOTREACHED;210} else {211change = true;212}213}214first.pc = NOTREACHED;215prev.next = null;216return change;217}218219/**220* Optimize the byte codes221*/222public void optimize(Environment env) {223//listing(System.out);224do {225// Figure out which instructions are reached226optimize(env, first);227228// Eliminate instructions that are not reached229} while (eliminate() && env.opt());230}231232/**233* Collect all constants into the constant table234*/235public void collect(Environment env, MemberDefinition field, ConstantPool tab) {236// Collect constants for arguments only237// if a local variable table is generated238if ((field != null) && env.debug_vars()) {239@SuppressWarnings("unchecked")240Vector<MemberDefinition> v = (Vector<MemberDefinition>)field.getArguments();241if (v != null) {242for (Enumeration<MemberDefinition> e = v.elements() ; e.hasMoreElements() ;) {243MemberDefinition f = e.nextElement();244tab.put(f.getName().toString());245tab.put(f.getType().getTypeSignature());246}247}248}249250// Collect constants from the instructions251for (Instruction inst = first ; inst != null ; inst = inst.next) {252inst.collect(tab);253}254}255256/**257* Determine stack size, count local variables258*/259void balance(Label lbl, int depth) {260for (Instruction inst = lbl ; inst != null ; inst = inst.next) {261//Environment.debugOutput(inst.toString() + ": " + depth + " => " +262// (depth + inst.balance()));263depth += inst.balance();264if (depth < 0) {265throw new CompilerError("stack under flow: " + inst.toString() + " = " + depth);266}267if (depth > maxdepth) {268maxdepth = depth;269}270switch (inst.opc) {271case opc_label:272lbl = (Label)inst;273if (inst.pc == REACHED) {274if (lbl.depth != depth) {275throw new CompilerError("stack depth error " +276depth + "/" + lbl.depth +277": " + inst.toString());278}279return;280}281lbl.pc = REACHED;282lbl.depth = depth;283break;284285case opc_ifeq:286case opc_ifne:287case opc_ifgt:288case opc_ifge:289case opc_iflt:290case opc_ifle:291case opc_if_icmpeq:292case opc_if_icmpne:293case opc_if_icmpgt:294case opc_if_icmpge:295case opc_if_icmplt:296case opc_if_icmple:297case opc_if_acmpeq:298case opc_if_acmpne:299case opc_ifnull:300case opc_ifnonnull:301balance((Label)inst.value, depth);302break;303304case opc_goto:305balance((Label)inst.value, depth);306return;307308case opc_jsr:309balance((Label)inst.value, depth + 1);310break;311312case opc_ret:313case opc_return:314case opc_ireturn:315case opc_lreturn:316case opc_freturn:317case opc_dreturn:318case opc_areturn:319case opc_athrow:320return;321322case opc_iload:323case opc_fload:324case opc_aload:325case opc_istore:326case opc_fstore:327case opc_astore: {328int v = ((inst.value instanceof Number)329? ((Number)inst.value).intValue()330: ((LocalVariable)inst.value).slot) + 1;331if (v > maxvar)332maxvar = v;333break;334}335336case opc_lload:337case opc_dload:338case opc_lstore:339case opc_dstore: {340int v = ((inst.value instanceof Number)341? ((Number)inst.value).intValue()342: ((LocalVariable)inst.value).slot) + 2;343if (v > maxvar)344maxvar = v;345break;346}347348case opc_iinc: {349int v = ((int[])inst.value)[0] + 1;350if (v > maxvar)351maxvar = v + 1;352break;353}354355case opc_tableswitch:356case opc_lookupswitch: {357SwitchData sw = (SwitchData)inst.value;358balance(sw.defaultLabel, depth);359for (Enumeration<Label> e = sw.tab.elements() ; e.hasMoreElements();) {360balance(e.nextElement(), depth);361}362return;363}364365case opc_try: {366TryData td = (TryData)inst.value;367for (Enumeration<CatchData> e = td.catches.elements() ; e.hasMoreElements();) {368CatchData cd = e.nextElement();369balance(cd.getLabel(), depth + 1);370}371break;372}373}374}375}376377/**378* Generate code379*/380public void write(Environment env, DataOutputStream out,381MemberDefinition field, ConstantPool tab)382throws IOException {383//listing(System.out);384385if ((field != null) && field.getArguments() != null) {386int sum = 0;387@SuppressWarnings("unchecked")388Vector<MemberDefinition> v = (Vector<MemberDefinition>)field.getArguments();389for (Enumeration<MemberDefinition> e = v.elements(); e.hasMoreElements(); ) {390MemberDefinition f = e.nextElement();391sum += f.getType().stackSize();392}393maxvar = sum;394}395396// Make sure the stack balances. Also calculate maxvar and maxstack397try {398balance(first, 0);399} catch (CompilerError e) {400System.out.println("ERROR: " + e);401listing(System.out);402throw e;403}404405// Assign PCs406int pc = 0, nexceptions = 0;407for (Instruction inst = first ; inst != null ; inst = inst.next) {408inst.pc = pc;409int sz = inst.size(tab);410if (pc<65536 && (pc+sz)>=65536) {411env.error(inst.where, "warn.method.too.long");412}413pc += sz;414415if (inst.opc == opc_try) {416nexceptions += ((TryData)inst.value).catches.size();417}418}419420// Write header421out.writeShort(maxdepth);422out.writeShort(maxvar);423out.writeInt(maxpc = pc);424425// Generate code426for (Instruction inst = first.next ; inst != null ; inst = inst.next) {427inst.write(out, tab);428}429430// write exceptions431out.writeShort(nexceptions);432if (nexceptions > 0) {433//listing(System.out);434writeExceptions(env, out, tab, first, last);435}436}437438/**439* Write the exceptions table440*/441void writeExceptions(Environment env, DataOutputStream out, ConstantPool tab, Instruction first, Instruction last) throws IOException {442for (Instruction inst = first ; inst != last.next ; inst = inst.next) {443if (inst.opc == opc_try) {444TryData td = (TryData)inst.value;445writeExceptions(env, out, tab, inst.next, td.getEndLabel());446for (Enumeration<CatchData> e = td.catches.elements() ; e.hasMoreElements();) {447CatchData cd = e.nextElement();448//System.out.println("EXCEPTION: " + env.getSource() + ", pc=" + inst.pc + ", end=" + td.getEndLabel().pc + ", hdl=" + cd.getLabel().pc + ", tp=" + cd.getType());449out.writeShort(inst.pc);450out.writeShort(td.getEndLabel().pc);451out.writeShort(cd.getLabel().pc);452if (cd.getType() != null) {453out.writeShort(tab.index(cd.getType()));454} else {455out.writeShort(0);456}457}458inst = td.getEndLabel();459}460}461}462463//JCOV464/**465* Write the coverage table466*/467public void writeCoverageTable(Environment env, ClassDefinition c, DataOutputStream out, ConstantPool tab, long whereField) throws IOException {468Vector<Cover> TableLot = new Vector<>(); /* Coverage table */469boolean begseg = false;470boolean begmeth = false;471@SuppressWarnings("deprecation")472long whereClass = ((SourceClass)c).getWhere();473Vector<Long> whereTry = new Vector<>();474int numberTry = 0;475int count = 0;476477for (Instruction inst = first ; inst != null ; inst = inst.next) {478long n = (inst.where >> WHEREOFFSETBITS);479if (n > 0 && inst.opc != opc_label) {480if (!begmeth) {481if ( whereClass == inst.where)482TableLot.addElement(new Cover(CT_FIKT_METHOD, whereField, inst.pc));483else484TableLot.addElement(new Cover(CT_METHOD, whereField, inst.pc));485count++;486begmeth = true;487}488if (!begseg && !inst.flagNoCovered ) {489boolean findTry = false;490for (Enumeration<Long> e = whereTry.elements(); e.hasMoreElements();) {491if (e.nextElement().longValue() == inst.where) {492findTry = true;493break;494}495}496if (!findTry) {497TableLot.addElement(new Cover(CT_BLOCK, inst.where, inst.pc));498count++;499begseg = true;500}501}502}503switch (inst.opc) {504case opc_label:505begseg = false;506break;507case opc_ifeq:508case opc_ifne:509case opc_ifnull:510case opc_ifnonnull:511case opc_ifgt:512case opc_ifge:513case opc_iflt:514case opc_ifle:515case opc_if_icmpeq:516case opc_if_icmpne:517case opc_if_icmpgt:518case opc_if_icmpge:519case opc_if_icmplt:520case opc_if_icmple:521case opc_if_acmpeq:522case opc_if_acmpne: {523if ( inst.flagCondInverted ) {524TableLot.addElement(new Cover(CT_BRANCH_TRUE, inst.where, inst.pc));525TableLot.addElement(new Cover(CT_BRANCH_FALSE, inst.where, inst.pc));526} else {527TableLot.addElement(new Cover(CT_BRANCH_FALSE, inst.where, inst.pc));528TableLot.addElement(new Cover(CT_BRANCH_TRUE, inst.where, inst.pc));529}530count += 2;531begseg = false;532break;533}534535case opc_goto: {536begseg = false;537break;538}539540case opc_ret:541case opc_return:542case opc_ireturn:543case opc_lreturn:544case opc_freturn:545case opc_dreturn:546case opc_areturn:547case opc_athrow: {548break;549}550551case opc_try: {552whereTry.addElement(Long.valueOf(inst.where));553begseg = false;554break;555}556557case opc_tableswitch: {558SwitchData sw = (SwitchData)inst.value;559for (int i = sw.minValue; i <= sw.maxValue; i++) {560TableLot.addElement(new Cover(CT_CASE, sw.whereCase(new Integer(i)), inst.pc));561count++;562}563if (!sw.getDefault()) {564TableLot.addElement(new Cover(CT_SWITH_WO_DEF, inst.where, inst.pc));565count++;566} else {567TableLot.addElement(new Cover(CT_CASE, sw.whereCase("default"), inst.pc));568count++;569}570begseg = false;571break;572}573case opc_lookupswitch: {574SwitchData sw = (SwitchData)inst.value;575for (Enumeration<Integer> e = sw.sortedKeys(); e.hasMoreElements() ; ) {576Integer v = e.nextElement();577TableLot.addElement(new Cover(CT_CASE, sw.whereCase(v), inst.pc));578count++;579}580if (!sw.getDefault()) {581TableLot.addElement(new Cover(CT_SWITH_WO_DEF, inst.where, inst.pc));582count++;583} else {584TableLot.addElement(new Cover(CT_CASE, sw.whereCase("default"), inst.pc));585count++;586}587begseg = false;588break;589}590}591}592Cover Lot;593long ln, pos;594595out.writeShort(count);596for (int i = 0; i < count; i++) {597Lot = TableLot.elementAt(i);598ln = (Lot.Addr >> WHEREOFFSETBITS);599pos = (Lot.Addr << (64 - WHEREOFFSETBITS)) >> (64 - WHEREOFFSETBITS);600out.writeShort(Lot.NumCommand);601out.writeShort(Lot.Type);602out.writeInt((int)ln);603out.writeInt((int)pos);604605if ( !(Lot.Type == CT_CASE && Lot.Addr == 0) ) {606JcovClassCountArray[Lot.Type]++;607}608}609610}611612/*613* Increase count of methods for native methods614*/615616public void addNativeToJcovTab(Environment env, ClassDefinition c) {617JcovClassCountArray[CT_METHOD]++;618}619620/*621* Create class jcov element622*/623624private String createClassJcovElement(Environment env, ClassDefinition c) {625String SourceClass = (Type.mangleInnerType((c.getClassDeclaration()).getName())).toString();626String ConvSourceClass;627String classJcovLine;628629SourceClassList.addElement(SourceClass);630ConvSourceClass = SourceClass.replace('.', '/');631classJcovLine = JcovClassLine + ConvSourceClass;632633classJcovLine = classJcovLine + " [";634String blank = "";635636for (int i = 0; i < arrayModifiers.length; i++ ) {637if ((c.getModifiers() & arrayModifiers[i]) != 0) {638classJcovLine = classJcovLine + blank + opNames[arrayModifiersOpc[i]];639blank = " ";640}641}642classJcovLine = classJcovLine + "]";643644return classJcovLine;645}646647/*648* generate coverage data649*/650651public void GenVecJCov(Environment env, ClassDefinition c, long Time) {652@SuppressWarnings("deprecation")653String SourceFile = ((SourceClass)c).getAbsoluteName();654655TmpCovTable.addElement(createClassJcovElement(env, c));656TmpCovTable.addElement(JcovSrcfileLine + SourceFile);657TmpCovTable.addElement(JcovTimestampLine + Time);658TmpCovTable.addElement(JcovDataLine + "A"); // data format659TmpCovTable.addElement(JcovHeadingLine);660661for (int i = CT_FIRST_KIND; i <= CT_LAST_KIND; i++) {662if (JcovClassCountArray[i] != 0) {663TmpCovTable.addElement(new String(i + "\t" + JcovClassCountArray[i]));664JcovClassCountArray[i] = 0;665}666}667}668669670/*671* generate file of coverage data672*/673674@SuppressWarnings("deprecation") // for JCovd.readLine() calls675public void GenJCov(Environment env) {676677try {678File outFile = env.getcovFile();679if( outFile.exists()) {680DataInputStream JCovd = new DataInputStream(681new BufferedInputStream(682new FileInputStream(outFile)));683String CurrLine = null;684boolean first = true;685String Class;686687CurrLine = JCovd.readLine();688if ((CurrLine != null) && CurrLine.startsWith(JcovMagicLine)) {689// this is a good Jcov file690691while((CurrLine = JCovd.readLine()) != null ) {692if ( CurrLine.startsWith(JcovClassLine) ) {693first = true;694for(Enumeration<String> e = SourceClassList.elements(); e.hasMoreElements();) {695String clsName = CurrLine.substring(JcovClassLine.length());696int idx = clsName.indexOf(' ');697698if (idx != -1) {699clsName = clsName.substring(0, idx);700}701Class = e.nextElement();702if ( Class.compareTo(clsName) == 0) {703first = false;704break;705}706}707}708if (first) // re-write old class709TmpCovTable.addElement(CurrLine);710}711}712JCovd.close();713}714PrintStream CovFile = new PrintStream(new DataOutputStream(new FileOutputStream(outFile)));715CovFile.println(JcovMagicLine);716for(Enumeration<String> e = TmpCovTable.elements(); e.hasMoreElements();) {717CovFile.println(e.nextElement());718}719CovFile.close();720}721catch (FileNotFoundException e) {722System.out.println("ERROR: " + e);723}724catch (IOException e) {725System.out.println("ERROR: " + e);726}727}728// end JCOV729730731/**732* Write the linenumber table733*/734public void writeLineNumberTable(Environment env, DataOutputStream out, ConstantPool tab) throws IOException {735long ln = -1;736int count = 0;737738for (Instruction inst = first ; inst != null ; inst = inst.next) {739long n = (inst.where >> WHEREOFFSETBITS);740if ((n > 0) && (ln != n)) {741ln = n;742count++;743}744}745746ln = -1;747out.writeShort(count);748for (Instruction inst = first ; inst != null ; inst = inst.next) {749long n = (inst.where >> WHEREOFFSETBITS);750if ((n > 0) && (ln != n)) {751ln = n;752out.writeShort(inst.pc);753out.writeShort((int)ln);754//System.out.println("pc = " + inst.pc + ", ln = " + ln);755}756}757}758759/**760* Figure out when registers contain a legal value. This is done761* using a simple data flow algorithm. This information is later used762* to generate the local variable table.763*/764void flowFields(Environment env, Label lbl, MemberDefinition locals[]) {765if (lbl.locals != null) {766// Been here before. Erase any conflicts.767MemberDefinition f[] = lbl.locals;768for (int i = 0 ; i < maxvar ; i++) {769if (f[i] != locals[i]) {770f[i] = null;771}772}773return;774}775776// Remember the set of active registers at this point777lbl.locals = new MemberDefinition[maxvar];778System.arraycopy(locals, 0, lbl.locals, 0, maxvar);779780MemberDefinition newlocals[] = new MemberDefinition[maxvar];781System.arraycopy(locals, 0, newlocals, 0, maxvar);782locals = newlocals;783784for (Instruction inst = lbl.next ; inst != null ; inst = inst.next) {785switch (inst.opc) {786case opc_istore: case opc_istore_0: case opc_istore_1:787case opc_istore_2: case opc_istore_3:788case opc_fstore: case opc_fstore_0: case opc_fstore_1:789case opc_fstore_2: case opc_fstore_3:790case opc_astore: case opc_astore_0: case opc_astore_1:791case opc_astore_2: case opc_astore_3:792case opc_lstore: case opc_lstore_0: case opc_lstore_1:793case opc_lstore_2: case opc_lstore_3:794case opc_dstore: case opc_dstore_0: case opc_dstore_1:795case opc_dstore_2: case opc_dstore_3:796if (inst.value instanceof LocalVariable) {797LocalVariable v = (LocalVariable)inst.value;798locals[v.slot] = v.field;799}800break;801802case opc_label:803flowFields(env, (Label)inst, locals);804return;805806case opc_ifeq: case opc_ifne: case opc_ifgt:807case opc_ifge: case opc_iflt: case opc_ifle:808case opc_if_icmpeq: case opc_if_icmpne: case opc_if_icmpgt:809case opc_if_icmpge: case opc_if_icmplt: case opc_if_icmple:810case opc_if_acmpeq: case opc_if_acmpne:811case opc_ifnull: case opc_ifnonnull:812case opc_jsr:813flowFields(env, (Label)inst.value, locals);814break;815816case opc_goto:817flowFields(env, (Label)inst.value, locals);818return;819820case opc_return: case opc_ireturn: case opc_lreturn:821case opc_freturn: case opc_dreturn: case opc_areturn:822case opc_athrow: case opc_ret:823return;824825case opc_tableswitch:826case opc_lookupswitch: {827SwitchData sw = (SwitchData)inst.value;828flowFields(env, sw.defaultLabel, locals);829for (Enumeration<Label> e = sw.tab.elements() ; e.hasMoreElements();) {830flowFields(env, e.nextElement(), locals);831}832return;833}834835case opc_try: {836Vector<CatchData> catches = ((TryData)inst.value).catches;837for (Enumeration<CatchData> e = catches.elements(); e.hasMoreElements();) {838CatchData cd = e.nextElement();839flowFields(env, cd.getLabel(), locals);840}841break;842}843}844}845}846847/**848* Write the local variable table. The necessary constants have already been849* added to the constant table by the collect() method. The flowFields method850* is used to determine which variables are alive at each pc.851*/852public void writeLocalVariableTable(Environment env, MemberDefinition field, DataOutputStream out, ConstantPool tab) throws IOException {853MemberDefinition locals[] = new MemberDefinition[maxvar];854int i = 0;855856// Initialize arguments857if ((field != null) && (field.getArguments() != null)) {858int reg = 0;859@SuppressWarnings("unchecked")860Vector<MemberDefinition> v = (Vector<MemberDefinition>)field.getArguments();861for (Enumeration<MemberDefinition> e = v.elements(); e.hasMoreElements(); ) {862MemberDefinition f = e.nextElement();863locals[reg] = f;864reg += f.getType().stackSize();865}866}867868flowFields(env, first, locals);869LocalVariableTable lvtab = new LocalVariableTable();870871// Initialize arguments again872for (i = 0; i < maxvar; i++)873locals[i] = null;874if ((field != null) && (field.getArguments() != null)) {875int reg = 0;876@SuppressWarnings("unchecked")877Vector<MemberDefinition> v = (Vector<MemberDefinition>)field.getArguments();878for (Enumeration<MemberDefinition> e = v.elements(); e.hasMoreElements(); ) {879MemberDefinition f = e.nextElement();880locals[reg] = f;881lvtab.define(f, reg, 0, maxpc);882reg += f.getType().stackSize();883}884}885886int pcs[] = new int[maxvar];887888for (Instruction inst = first ; inst != null ; inst = inst.next) {889switch (inst.opc) {890case opc_istore: case opc_istore_0: case opc_istore_1:891case opc_istore_2: case opc_istore_3: case opc_fstore:892case opc_fstore_0: case opc_fstore_1: case opc_fstore_2:893case opc_fstore_3:894case opc_astore: case opc_astore_0: case opc_astore_1:895case opc_astore_2: case opc_astore_3:896case opc_lstore: case opc_lstore_0: case opc_lstore_1:897case opc_lstore_2: case opc_lstore_3:898case opc_dstore: case opc_dstore_0: case opc_dstore_1:899case opc_dstore_2: case opc_dstore_3:900if (inst.value instanceof LocalVariable) {901LocalVariable v = (LocalVariable)inst.value;902int pc = (inst.next != null) ? inst.next.pc : inst.pc;903if (locals[v.slot] != null) {904lvtab.define(locals[v.slot], v.slot, pcs[v.slot], pc);905}906pcs[v.slot] = pc;907locals[v.slot] = v.field;908}909break;910911case opc_label: {912// flush previous labels913for (i = 0 ; i < maxvar ; i++) {914if (locals[i] != null) {915lvtab.define(locals[i], i, pcs[i], inst.pc);916}917}918// init new labels919int pc = inst.pc;920MemberDefinition[] labelLocals = ((Label)inst).locals;921if (labelLocals == null) { // unreachable code??922for (i = 0; i < maxvar; i++)923locals[i] = null;924} else {925System.arraycopy(labelLocals, 0, locals, 0, maxvar);926}927for (i = 0 ; i < maxvar ; i++) {928pcs[i] = pc;929}930break;931}932}933}934935// flush remaining labels936for (i = 0 ; i < maxvar ; i++) {937if (locals[i] != null) {938lvtab.define(locals[i], i, pcs[i], maxpc);939}940}941942// write the local variable table943lvtab.write(env, out, tab);944}945946/**947* Return true if empty948*/949public boolean empty() {950return first == last;951}952953/**954* Print the byte codes955*/956public void listing(PrintStream out) {957out.println("-- listing --");958for (Instruction inst = first ; inst != null ; inst = inst.next) {959out.println(inst.toString());960}961}962}963964965