src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/util/MethodGenerator.java
changeset 47359 e1a6c0168741
parent 47216 71c04702a3d5
child 47712 bde0215f1f70
equal deleted inserted replaced
47358:d07d5f7cab35 47359:e1a6c0168741
     1 /*
     1 /*
     2  * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
       
     3  * @LastModified: Oct 2017
     3  */
     4  */
     4 /*
     5 /*
     5  * Licensed to the Apache Software Foundation (ASF) under one or more
     6  * Licensed to the Apache Software Foundation (ASF) under one or more
     6  * contributor license agreements.  See the NOTICE file distributed with
     7  * contributor license agreements.  See the NOTICE file distributed with
     7  * this work for additional information regarding copyright ownership.
     8  * this work for additional information regarding copyright ownership.
    21  * $Id: MethodGenerator.java,v 1.2.4.1 2005/09/05 11:16:47 pvedula Exp $
    22  * $Id: MethodGenerator.java,v 1.2.4.1 2005/09/05 11:16:47 pvedula Exp $
    22  */
    23  */
    23 
    24 
    24 package com.sun.org.apache.xalan.internal.xsltc.compiler.util;
    25 package com.sun.org.apache.xalan.internal.xsltc.compiler.util;
    25 
    26 
    26 import java.util.ArrayList;
       
    27 import java.util.Collections;
       
    28 import java.util.HashMap;
       
    29 import java.util.Iterator;
       
    30 import java.util.Map;
       
    31 import java.util.Stack;
       
    32 
       
    33 
       
    34 import com.sun.org.apache.bcel.internal.Const;
    27 import com.sun.org.apache.bcel.internal.Const;
    35 import com.sun.org.apache.bcel.internal.classfile.Field;
    28 import com.sun.org.apache.bcel.internal.classfile.Field;
    36 import com.sun.org.apache.bcel.internal.classfile.Method;
    29 import com.sun.org.apache.bcel.internal.classfile.Method;
    37 import com.sun.org.apache.bcel.internal.generic.ALOAD;
    30 import com.sun.org.apache.bcel.internal.generic.ALOAD;
    38 import com.sun.org.apache.bcel.internal.generic.ASTORE;
    31 import com.sun.org.apache.bcel.internal.generic.ASTORE;
    44 import com.sun.org.apache.bcel.internal.generic.FLOAD;
    37 import com.sun.org.apache.bcel.internal.generic.FLOAD;
    45 import com.sun.org.apache.bcel.internal.generic.FSTORE;
    38 import com.sun.org.apache.bcel.internal.generic.FSTORE;
    46 import com.sun.org.apache.bcel.internal.generic.GETFIELD;
    39 import com.sun.org.apache.bcel.internal.generic.GETFIELD;
    47 import com.sun.org.apache.bcel.internal.generic.GOTO;
    40 import com.sun.org.apache.bcel.internal.generic.GOTO;
    48 import com.sun.org.apache.bcel.internal.generic.ICONST;
    41 import com.sun.org.apache.bcel.internal.generic.ICONST;
    49 import com.sun.org.apache.bcel.internal.generic.IfInstruction;
       
    50 import com.sun.org.apache.bcel.internal.generic.ILOAD;
    42 import com.sun.org.apache.bcel.internal.generic.ILOAD;
    51 import com.sun.org.apache.bcel.internal.generic.IndexedInstruction;
       
    52 import com.sun.org.apache.bcel.internal.generic.INVOKEINTERFACE;
    43 import com.sun.org.apache.bcel.internal.generic.INVOKEINTERFACE;
    53 import com.sun.org.apache.bcel.internal.generic.INVOKESPECIAL;
    44 import com.sun.org.apache.bcel.internal.generic.INVOKESPECIAL;
    54 import com.sun.org.apache.bcel.internal.generic.INVOKESTATIC;
    45 import com.sun.org.apache.bcel.internal.generic.INVOKESTATIC;
    55 import com.sun.org.apache.bcel.internal.generic.INVOKEVIRTUAL;
    46 import com.sun.org.apache.bcel.internal.generic.INVOKEVIRTUAL;
    56 import com.sun.org.apache.bcel.internal.generic.ISTORE;
    47 import com.sun.org.apache.bcel.internal.generic.ISTORE;
       
    48 import com.sun.org.apache.bcel.internal.generic.IfInstruction;
       
    49 import com.sun.org.apache.bcel.internal.generic.IndexedInstruction;
    57 import com.sun.org.apache.bcel.internal.generic.Instruction;
    50 import com.sun.org.apache.bcel.internal.generic.Instruction;
    58 import com.sun.org.apache.bcel.internal.generic.InstructionConst;
    51 import com.sun.org.apache.bcel.internal.generic.InstructionConst;
    59 import com.sun.org.apache.bcel.internal.generic.InstructionHandle;
    52 import com.sun.org.apache.bcel.internal.generic.InstructionHandle;
    60 import com.sun.org.apache.bcel.internal.generic.InstructionList;
    53 import com.sun.org.apache.bcel.internal.generic.InstructionList;
    61 import com.sun.org.apache.bcel.internal.generic.InstructionTargeter;
    54 import com.sun.org.apache.bcel.internal.generic.InstructionTargeter;
       
    55 import com.sun.org.apache.bcel.internal.generic.LLOAD;
       
    56 import com.sun.org.apache.bcel.internal.generic.LSTORE;
    62 import com.sun.org.apache.bcel.internal.generic.LocalVariableGen;
    57 import com.sun.org.apache.bcel.internal.generic.LocalVariableGen;
    63 import com.sun.org.apache.bcel.internal.generic.LocalVariableInstruction;
    58 import com.sun.org.apache.bcel.internal.generic.LocalVariableInstruction;
    64 import com.sun.org.apache.bcel.internal.generic.LLOAD;
       
    65 import com.sun.org.apache.bcel.internal.generic.LSTORE;
       
    66 import com.sun.org.apache.bcel.internal.generic.MethodGen;
    59 import com.sun.org.apache.bcel.internal.generic.MethodGen;
    67 import com.sun.org.apache.bcel.internal.generic.NEW;
    60 import com.sun.org.apache.bcel.internal.generic.NEW;
    68 import com.sun.org.apache.bcel.internal.generic.PUTFIELD;
    61 import com.sun.org.apache.bcel.internal.generic.PUTFIELD;
    69 import com.sun.org.apache.bcel.internal.generic.RET;
    62 import com.sun.org.apache.bcel.internal.generic.RET;
    70 import com.sun.org.apache.bcel.internal.generic.Select;
    63 import com.sun.org.apache.bcel.internal.generic.Select;
    71 import com.sun.org.apache.bcel.internal.generic.TargetLostException;
    64 import com.sun.org.apache.bcel.internal.generic.TargetLostException;
    72 import com.sun.org.apache.bcel.internal.generic.Type;
    65 import com.sun.org.apache.bcel.internal.generic.Type;
    73 
       
    74 import com.sun.org.apache.xalan.internal.xsltc.compiler.Pattern;
    66 import com.sun.org.apache.xalan.internal.xsltc.compiler.Pattern;
    75 import com.sun.org.apache.xalan.internal.xsltc.compiler.XSLTC;
    67 import com.sun.org.apache.xalan.internal.xsltc.compiler.XSLTC;
       
    68 import java.util.ArrayList;
       
    69 import java.util.Collections;
       
    70 import java.util.HashMap;
       
    71 import java.util.Iterator;
       
    72 import java.util.List;
       
    73 import java.util.Map;
       
    74 import java.util.Stack;
    76 
    75 
    77 /**
    76 /**
    78  * @author Jacek Ambroziak
    77  * @author Jacek Ambroziak
    79  * @author Santiago Pericas-Geertsen
    78  * @author Santiago Pericas-Geertsen
    80  */
    79  */
   264      * {@link #outline(InstructionHandle,InstructionHandle,String,ClassGenerator)},
   263      * {@link #outline(InstructionHandle,InstructionHandle,String,ClassGenerator)},
   265      * this class keeps track of all local variables defined by the method.</p>
   264      * this class keeps track of all local variables defined by the method.</p>
   266      */
   265      */
   267     protected class LocalVariableRegistry {
   266     protected class LocalVariableRegistry {
   268         /**
   267         /**
   269          * <p>A <code>java.lang.ArrayList</code> of all
   268          * <p>A <code>java.lang.List</code> of all
   270          * {@link LocalVariableGen}s created for this method, indexed by the
   269          * {@link LocalVariableGen}s created for this method, indexed by the
   271          * slot number of the local variable.  The JVM stack frame of local
   270          * slot number of the local variable.  The JVM stack frame of local
   272          * variables is divided into "slots".  A single slot can be used to
   271          * variables is divided into "slots".  A single slot can be used to
   273          * store more than one variable in a method, without regard to type, so
   272          * store more than one variable in a method, without regard to type, so
   274          * long as the byte code keeps the ranges of the two disjoint.</p>
   273          * long as the byte code keeps the ranges of the two disjoint.</p>
   277          * <code>LocalVariableGen</code>; if more than one occurs, the
   276          * <code>LocalVariableGen</code>; if more than one occurs, the
   278          * corresponding entry contains all such <code>LocalVariableGen</code>s
   277          * corresponding entry contains all such <code>LocalVariableGen</code>s
   279          * registered for the same slot; and if none occurs, the entry will be
   278          * registered for the same slot; and if none occurs, the entry will be
   280          * <code>null</code>.
   279          * <code>null</code>.
   281          */
   280          */
   282         protected ArrayList _variables = new ArrayList();
   281         protected List<Object> _variables = new ArrayList<>();
   283 
   282 
   284         /**
   283         /**
   285          * Maps a name to a {@link LocalVariableGen}
   284          * Maps a name to a {@link LocalVariableGen}
   286          */
   285          */
   287         protected HashMap _nameToLVGMap = new HashMap();
   286         protected Map<String, Object> _nameToLVGMap = new HashMap<>();
   288 
   287 
   289         /**
   288         /**
   290          * Registers a {@link org.apache.bcel.generic.LocalVariableGen}
   289          * Registers a {@link org.apache.bcel.generic.LocalVariableGen}
   291          * for this method.
   290          * for this method.
   292          * <p><b>Preconditions:</b>
   291          * <p><b>Preconditions:</b>
   296          * <code>LocalVariableGen</code> with the same slot index previously
   295          * <code>LocalVariableGen</code> with the same slot index previously
   297          * registered for this method.  <b><em>(Unchecked.)</em></b></li>
   296          * registered for this method.  <b><em>(Unchecked.)</em></b></li>
   298          * </ul></p>
   297          * </ul></p>
   299          * @param lvg The variable to be registered
   298          * @param lvg The variable to be registered
   300          */
   299          */
       
   300         @SuppressWarnings("unchecked")
   301         protected void registerLocalVariable(LocalVariableGen lvg) {
   301         protected void registerLocalVariable(LocalVariableGen lvg) {
   302             int slot = lvg.getIndex();
   302             int slot = lvg.getIndex();
   303 
   303 
   304             int registrySize = _variables.size();
   304             int registrySize = _variables.size();
   305 
   305 
   318                 // _variables just contains null padding, store the
   318                 // _variables just contains null padding, store the
   319                 // LocalVariableGen directly.
   319                 // LocalVariableGen directly.
   320                 Object localsInSlot = _variables.get(slot);
   320                 Object localsInSlot = _variables.get(slot);
   321                 if (localsInSlot != null) {
   321                 if (localsInSlot != null) {
   322                     if (localsInSlot instanceof LocalVariableGen) {
   322                     if (localsInSlot instanceof LocalVariableGen) {
   323                         ArrayList listOfLocalsInSlot = new ArrayList();
   323                         List<LocalVariableGen> listOfLocalsInSlot = new ArrayList<>();
   324                         listOfLocalsInSlot.add(localsInSlot);
   324                         listOfLocalsInSlot.add((LocalVariableGen)localsInSlot);
   325                         listOfLocalsInSlot.add(lvg);
   325                         listOfLocalsInSlot.add(lvg);
   326                         _variables.set(slot, listOfLocalsInSlot);
   326                         _variables.set(slot, listOfLocalsInSlot);
   327                     } else {
   327                     } else {
   328                         ((ArrayList) localsInSlot).add(lvg);
   328                         ((List<LocalVariableGen>) localsInSlot).add(lvg);
   329                     }
   329                     }
   330                 } else {
   330                 } else {
   331                     _variables.set(slot, lvg);
   331                     _variables.set(slot, lvg);
   332                 }
   332                 }
   333             }
   333             }
   367                     LocalVariableGen lvg = (LocalVariableGen)localsInSlot;
   367                     LocalVariableGen lvg = (LocalVariableGen)localsInSlot;
   368                     if (offsetInLocalVariableGenRange(lvg, offset)) {
   368                     if (offsetInLocalVariableGenRange(lvg, offset)) {
   369                         return lvg;
   369                         return lvg;
   370                     }
   370                     }
   371                 } else {
   371                 } else {
   372                     ArrayList listOfLocalsInSlot = (ArrayList) localsInSlot;
   372                     @SuppressWarnings("unchecked")
   373                     int size = listOfLocalsInSlot.size();
   373                     List<LocalVariableGen> listOfLocalsInSlot =
   374 
   374                             (List<LocalVariableGen>) localsInSlot;
   375                     for (int i = 0; i < size; i++) {
   375 
   376                         LocalVariableGen lvg =
   376                     for (LocalVariableGen lvg : listOfLocalsInSlot) {
   377                             (LocalVariableGen)listOfLocalsInSlot.get(i);
       
   378                         if (offsetInLocalVariableGenRange(lvg, offset)) {
   377                         if (offsetInLocalVariableGenRange(lvg, offset)) {
   379                             return lvg;
   378                             return lvg;
   380                         }
   379                         }
   381                     }
   380                     }
   382                 }
   381                 }
   401          * set, which causes problems for outlining..</p>
   400          * set, which causes problems for outlining..</p>
   402          * <p>See also {@link #lookUpByName(String)} and
   401          * <p>See also {@link #lookUpByName(String)} and
   403          * {@link #removeByNameTracking(LocalVariableGen)}</P
   402          * {@link #removeByNameTracking(LocalVariableGen)}</P
   404          * @param lvg a <code>LocalVariableGen</code>
   403          * @param lvg a <code>LocalVariableGen</code>
   405          */
   404          */
       
   405         @SuppressWarnings("unchecked")
   406         protected void registerByName(LocalVariableGen lvg) {
   406         protected void registerByName(LocalVariableGen lvg) {
   407             Object duplicateNameEntry = _nameToLVGMap.get(lvg.getName());
   407             Object duplicateNameEntry = _nameToLVGMap.get(lvg.getName());
   408 
   408 
   409             if (duplicateNameEntry == null) {
   409             if (duplicateNameEntry == null) {
   410                 _nameToLVGMap.put(lvg.getName(), lvg);
   410                 _nameToLVGMap.put(lvg.getName(), lvg);
   411             } else {
   411             } else {
   412                 ArrayList sameNameList;
   412                 List<LocalVariableGen> sameNameList;
   413 
   413 
   414                 if (duplicateNameEntry instanceof ArrayList) {
   414                 if (duplicateNameEntry instanceof ArrayList) {
   415                     sameNameList = (ArrayList) duplicateNameEntry;
   415                     sameNameList = (List<LocalVariableGen>)duplicateNameEntry;
   416                     sameNameList.add(lvg);
   416                     sameNameList.add(lvg);
   417                 } else {
   417                 } else {
   418                     sameNameList = new ArrayList();
   418                     sameNameList = new ArrayList<>();
   419                     sameNameList.add(duplicateNameEntry);
   419                     sameNameList.add((LocalVariableGen)duplicateNameEntry);
   420                     sameNameList.add(lvg);
   420                     sameNameList.add(lvg);
   421                 }
   421                 }
   422 
   422 
   423                 _nameToLVGMap.put(lvg.getName(), sameNameList);
   423                 _nameToLVGMap.put(lvg.getName(), sameNameList);
   424             }
   424             }
   429          * {@link LocalVariableGen} to itself.
   429          * {@link LocalVariableGen} to itself.
   430          * See also {@link #registerByName(LocalVariableGen)} and
   430          * See also {@link #registerByName(LocalVariableGen)} and
   431          * {@link #lookUpByName(String)}
   431          * {@link #lookUpByName(String)}
   432          * @param lvg a <code>LocalVariableGen</code>
   432          * @param lvg a <code>LocalVariableGen</code>
   433          */
   433          */
       
   434         @SuppressWarnings("unchecked")
   434         protected void removeByNameTracking(LocalVariableGen lvg) {
   435         protected void removeByNameTracking(LocalVariableGen lvg) {
   435             Object duplicateNameEntry = _nameToLVGMap.get(lvg.getName());
   436             Object duplicateNameEntry = _nameToLVGMap.get(lvg.getName());
   436 
   437 
   437             if (duplicateNameEntry instanceof ArrayList) {
   438             if (duplicateNameEntry instanceof ArrayList) {
   438                 ArrayList sameNameList = (ArrayList) duplicateNameEntry;
   439                 List<LocalVariableGen> sameNameList =
       
   440                         (List<LocalVariableGen>)duplicateNameEntry;
   439                 for (int i = 0; i < sameNameList.size(); i++) {
   441                 for (int i = 0; i < sameNameList.size(); i++) {
   440                     if (sameNameList.get(i) == lvg) {
   442                     if (sameNameList.get(i) == lvg) {
   441                         sameNameList.remove(i);
   443                         sameNameList.remove(i);
   442                         break;
   444                         break;
   443                     }
   445                     }
   453          * <p>See also {@link #registerByName(LocalVariableGen)} and
   455          * <p>See also {@link #registerByName(LocalVariableGen)} and
   454          * {@link #removeByNameTracking(LocalVariableGen)}</p>
   456          * {@link #removeByNameTracking(LocalVariableGen)}</p>
   455          * @param name
   457          * @param name
   456          * @return
   458          * @return
   457          */
   459          */
       
   460         @SuppressWarnings("unchecked")
   458         protected LocalVariableGen lookUpByName(String name) {
   461         protected LocalVariableGen lookUpByName(String name) {
   459             LocalVariableGen lvg = null;
   462             LocalVariableGen lvg = null;
   460             Object duplicateNameEntry = _nameToLVGMap.get(name);
   463             Object duplicateNameEntry = _nameToLVGMap.get(name);
   461 
   464 
   462             if (duplicateNameEntry instanceof ArrayList) {
   465             if (duplicateNameEntry instanceof ArrayList) {
   463                 ArrayList sameNameList = (ArrayList) duplicateNameEntry;
   466                 List<LocalVariableGen> sameNameList =
       
   467                         (List<LocalVariableGen>)duplicateNameEntry;
   464 
   468 
   465                 for (int i = 0; i < sameNameList.size(); i++) {
   469                 for (int i = 0; i < sameNameList.size(); i++) {
   466                     lvg = (LocalVariableGen)sameNameList.get(i);
   470                     lvg = sameNameList.get(i);
   467                     if (lvg.getName() == name) {
   471                     if (lvg.getName() == null ? name == null : lvg.getName().equals(name)) {
   468                         break;
   472                         break;
   469                     }
   473                     }
   470                 }
   474                 }
   471             } else {
   475             } else {
   472                 lvg = (LocalVariableGen) duplicateNameEntry;
   476                 lvg = (LocalVariableGen) duplicateNameEntry;
   487          * declared should be returned (<code>true</code>) or only those not
   491          * declared should be returned (<code>true</code>) or only those not
   488          * removed (<code>false</code>)
   492          * removed (<code>false</code>)
   489          * @return an array of <code>LocalVariableGen</code> containing all the
   493          * @return an array of <code>LocalVariableGen</code> containing all the
   490          * local variables
   494          * local variables
   491          */
   495          */
       
   496         @SuppressWarnings("unchecked")
   492         protected LocalVariableGen[] getLocals(boolean includeRemoved) {
   497         protected LocalVariableGen[] getLocals(boolean includeRemoved) {
   493             LocalVariableGen[] locals = null;
   498             LocalVariableGen[] locals = null;
   494             ArrayList allVarsEverDeclared = new ArrayList();
   499             List<LocalVariableGen> allVarsEverDeclared = new ArrayList<>();
   495 
   500 
   496             if (includeRemoved) {
   501             if (includeRemoved) {
   497                 int slotCount = allVarsEverDeclared.size();
   502                 int slotCount = allVarsEverDeclared.size();
   498 
   503 
   499                 for (int i = 0; i < slotCount; i++) {
   504                 for (int i = 0; i < slotCount; i++) {
   500                     Object slotEntries = _variables.get(i);
   505                     Object slotEntries = _variables.get(i);
   501                     if (slotEntries != null) {
   506                     if (slotEntries != null) {
   502                         if (slotEntries instanceof ArrayList) {
   507                         if (slotEntries instanceof ArrayList) {
   503                             ArrayList slotList = (ArrayList) slotEntries;
   508                             List<LocalVariableGen> slotList =
       
   509                                     (List<LocalVariableGen>)slotEntries;
   504 
   510 
   505                             for (int j = 0; j < slotList.size(); j++) {
   511                             for (int j = 0; j < slotList.size(); j++) {
   506                                 allVarsEverDeclared.add(slotList.get(i));
   512                                 allVarsEverDeclared.add(slotList.get(i));
   507                             }
   513                             }
   508                         } else {
   514                         } else {
   509                             allVarsEverDeclared.add(slotEntries);
   515                             allVarsEverDeclared.add((LocalVariableGen)slotEntries);
   510                         }
   516                         }
   511                     }
   517                     }
   512                 }
   518                 }
   513             } else {
   519             } else {
   514                 Iterator nameVarsPairsIter = _nameToLVGMap.entrySet().iterator();
   520                 for (Map.Entry<String, Object> nameVarsPair : _nameToLVGMap.entrySet()) {
   515 
       
   516                 while (nameVarsPairsIter.hasNext()) {
       
   517                     Map.Entry nameVarsPair =
       
   518                                   (Map.Entry) nameVarsPairsIter.next();
       
   519                     Object vars = nameVarsPair.getValue();
   521                     Object vars = nameVarsPair.getValue();
   520                     if (vars != null) {
   522                     if (vars != null) {
   521                         if (vars instanceof ArrayList) {
   523                         if (vars instanceof ArrayList) {
   522                             ArrayList varsList = (ArrayList) vars;
   524                             List<LocalVariableGen> varsList =
       
   525                                     (List<LocalVariableGen>) vars;
   523                             for (int i = 0; i < varsList.size(); i++) {
   526                             for (int i = 0; i < varsList.size(); i++) {
   524                                 allVarsEverDeclared.add(varsList.get(i));
   527                                 allVarsEverDeclared.add(varsList.get(i));
   525                             }
   528                             }
   526                         } else {
   529                         } else {
   527                             allVarsEverDeclared.add(vars);
   530                             allVarsEverDeclared.add((LocalVariableGen)vars);
   528                         }
   531                         }
   529                     }
   532                     }
   530                 }
   533                 }
   531             }
   534             }
   532 
   535 
   718     /**
   721     /**
   719      * Used to keep track of an outlineable chunk of instructions in the
   722      * Used to keep track of an outlineable chunk of instructions in the
   720      * current method.  See {@link OutlineableChunkStart} and
   723      * current method.  See {@link OutlineableChunkStart} and
   721      * {@link OutlineableChunkEnd} for more information.
   724      * {@link OutlineableChunkEnd} for more information.
   722      */
   725      */
   723     private class Chunk implements Comparable {
   726     private class Chunk implements Comparable<Object> {
   724         /**
   727         /**
   725          * {@link InstructionHandle} of the first instruction in the outlineable
   728          * {@link InstructionHandle} of the first instruction in the outlineable
   726          * chunk.
   729          * chunk.
   727          */
   730          */
   728         private InstructionHandle m_start;
   731         private InstructionHandle m_start;
   819      * Find the outlineable chunks in this method that would be the best choices
   822      * Find the outlineable chunks in this method that would be the best choices
   820      * to outline, based on size and position in the method.
   823      * to outline, based on size and position in the method.
   821      * @param classGen The {@link ClassGen} with which the generated methods
   824      * @param classGen The {@link ClassGen} with which the generated methods
   822      *                 will be associated
   825      *                 will be associated
   823      * @param totalMethodSize the size of the bytecode in the original method
   826      * @param totalMethodSize the size of the bytecode in the original method
   824      * @return a <code>java.util.ArrayList</code> containing the
   827      * @return a <code>java.util.List</code> containing the
   825      *  {@link MethodGenerator.Chunk}s that may be outlined from this method
   828      *  {@link MethodGenerator.Chunk}s that may be outlined from this method
   826      */
   829      */
   827     private ArrayList getCandidateChunks(ClassGenerator classGen,
   830     private List<Chunk> getCandidateChunks(ClassGenerator classGen,
   828                                          int totalMethodSize) {
   831                                          int totalMethodSize) {
   829         Iterator instructions = getInstructionList().iterator();
   832         Iterator<InstructionHandle> instructions = getInstructionList().iterator();
   830         ArrayList candidateChunks = new ArrayList();
   833         List<Chunk> candidateChunks = new ArrayList<>();
   831         ArrayList currLevelChunks = new ArrayList();
   834         List<InstructionHandle> currLevelChunks = new ArrayList<>();
   832         Stack subChunkStack = new Stack();
   835         Stack<List<InstructionHandle>> subChunkStack = new Stack<>();
   833         boolean openChunkAtCurrLevel = false;
   836         boolean openChunkAtCurrLevel = false;
   834         boolean firstInstruction = true;
   837         boolean firstInstruction = true;
   835 
   838 
   836         InstructionHandle currentHandle;
   839         InstructionHandle currentHandle;
   837 
   840 
   882                 // OutlineableChunkStart, this represents the first chunk
   885                 // OutlineableChunkStart, this represents the first chunk
   883                 // nested within that previous chunk - push the list of chunks
   886                 // nested within that previous chunk - push the list of chunks
   884                 // from the outer level onto the stack
   887                 // from the outer level onto the stack
   885                 if (openChunkAtCurrLevel) {
   888                 if (openChunkAtCurrLevel) {
   886                     subChunkStack.push(currLevelChunks);
   889                     subChunkStack.push(currLevelChunks);
   887                     currLevelChunks = new ArrayList();
   890                     currLevelChunks = new ArrayList<>();
   888                 }
   891                 }
   889 
   892 
   890                 openChunkAtCurrLevel = true;
   893                 openChunkAtCurrLevel = true;
   891                 currLevelChunks.add(currentHandle);
   894                 currLevelChunks.add(currentHandle);
   892             // Close off an open chunk
   895             // Close off an open chunk
   893             } else if (currentHandle == null
   896             } else if (currentHandle == null
   894                            || inst instanceof OutlineableChunkEnd) {
   897                            || inst instanceof OutlineableChunkEnd) {
   895                 ArrayList nestedSubChunks = null;
   898                 List<InstructionHandle> nestedSubChunks = null;
   896 
   899 
   897                 // If the last MarkerInstruction encountered was an
   900                 // If the last MarkerInstruction encountered was an
   898                 // OutlineableChunkEnd, it means that the current instruction
   901                 // OutlineableChunkEnd, it means that the current instruction
   899                 // marks the end of a chunk that contained child chunks.
   902                 // marks the end of a chunk that contained child chunks.
   900                 // Those children might need to be examined below in case they
   903                 // Those children might need to be examined below in case they
   901                 // are better candidates for outlining than the current chunk.
   904                 // are better candidates for outlining than the current chunk.
   902                 if (!openChunkAtCurrLevel) {
   905                 if (!openChunkAtCurrLevel) {
   903                     nestedSubChunks = currLevelChunks;
   906                     nestedSubChunks = currLevelChunks;
   904                     currLevelChunks = (ArrayList)subChunkStack.pop();
   907                     currLevelChunks = (List<InstructionHandle>)subChunkStack.pop();
   905                 }
   908                 }
   906 
   909 
   907                 // Get the handle for the start of this chunk (the last entry
   910                 // Get the handle for the start of this chunk (the last entry
   908                 // in currLevelChunks)
   911                 // in currLevelChunks)
   909                 InstructionHandle chunkStart =
   912                 InstructionHandle chunkStart =
   946 
   949 
   947                                 childChunks[i] = new Chunk(start, end);
   950                                 childChunks[i] = new Chunk(start, end);
   948                             }
   951                             }
   949 
   952 
   950                             // Merge adjacent siblings
   953                             // Merge adjacent siblings
   951                             ArrayList mergedChildChunks =
   954                             List<Chunk> mergedChildChunks =
   952                                         mergeAdjacentChunks(childChunks);
   955                                         mergeAdjacentChunks(childChunks);
   953 
   956 
   954                             // Add chunks that mean minimum size requirements
   957                             // Add chunks that mean minimum size requirements
   955                             // to the list of candidate chunks for outlining
   958                             // to the list of candidate chunks for outlining
   956                             for (int i = 0; i < mergedChildChunks.size(); i++) {
   959                             for (Chunk mergedChunk : mergedChildChunks) {
   957                                 Chunk mergedChunk =
       
   958                                     (Chunk)mergedChildChunks.get(i);
       
   959                                 int mergedSize = mergedChunk.getChunkSize();
   960                                 int mergedSize = mergedChunk.getChunkSize();
   960 
   961 
   961                                 if (mergedSize >= MINIMUM_OUTLINEABLE_CHUNK_SIZE
   962                                 if (mergedSize >= MINIMUM_OUTLINEABLE_CHUNK_SIZE
   962                                         && mergedSize <= TARGET_METHOD_SIZE) {
   963                                         && mergedSize <= TARGET_METHOD_SIZE) {
   963                                     candidateChunks.add(mergedChunk);
   964                                     candidateChunks.add(mergedChunk);
   985      * Merge adjacent sibling chunks to produce larger candidate chunks for
   986      * Merge adjacent sibling chunks to produce larger candidate chunks for
   986      * outlining
   987      * outlining
   987      * @param chunks array of sibling {@link MethodGenerator.Chunk}s that are
   988      * @param chunks array of sibling {@link MethodGenerator.Chunk}s that are
   988      *               under consideration for outlining.  Chunks must be in
   989      *               under consideration for outlining.  Chunks must be in
   989      *               the order encountered in the {@link InstructionList}
   990      *               the order encountered in the {@link InstructionList}
   990      * @return a <code>java.util.ArrayList</code> of
   991      * @return a <code>java.util.List</code> of
   991      *         <code>MethodGenerator.Chunk</code>s maximally merged
   992      *         <code>MethodGenerator.Chunk</code>s maximally merged
   992      */
   993      */
   993     private ArrayList mergeAdjacentChunks(Chunk[] chunks) {
   994     private List<Chunk> mergeAdjacentChunks(Chunk[] chunks) {
   994         int[] adjacencyRunStart = new int[chunks.length];
   995         int[] adjacencyRunStart = new int[chunks.length];
   995         int[] adjacencyRunLength = new int[chunks.length];
   996         int[] adjacencyRunLength = new int[chunks.length];
   996         boolean[] chunkWasMerged = new boolean[chunks.length];
   997         boolean[] chunkWasMerged = new boolean[chunks.length];
   997 
   998 
   998         int maximumRunOfChunks = 0;
   999         int maximumRunOfChunks = 0;
   999         int startOfCurrentRun;
  1000         int startOfCurrentRun;
  1000         int numAdjacentRuns = 0;
  1001         int numAdjacentRuns = 0;
  1001 
  1002 
  1002         ArrayList mergedChunks = new ArrayList();
  1003         List<Chunk> mergedChunks = new ArrayList<>();
  1003 
  1004 
  1004         startOfCurrentRun = 0;
  1005         startOfCurrentRun = 0;
  1005 
  1006 
  1006         // Loop through chunks, and record in adjacencyRunStart where each
  1007         // Loop through chunks, and record in adjacencyRunStart where each
  1007         // run of adjacent chunks begins and how many are in that run.  For
  1008         // run of adjacent chunks begins and how many are in that run.  For
  1131      * @return an array of the outlined <code>Method</code>s and the original
  1132      * @return an array of the outlined <code>Method</code>s and the original
  1132      *         method itself
  1133      *         method itself
  1133      */
  1134      */
  1134     public Method[] outlineChunks(ClassGenerator classGen,
  1135     public Method[] outlineChunks(ClassGenerator classGen,
  1135                                   int originalMethodSize) {
  1136                                   int originalMethodSize) {
  1136         ArrayList methodsOutlined = new ArrayList();
  1137         List<Method> methodsOutlined = new ArrayList<>();
  1137         int currentMethodSize = originalMethodSize;
  1138         int currentMethodSize = originalMethodSize;
  1138 
  1139 
  1139         int outlinedCount = 0;
  1140         int outlinedCount = 0;
  1140         boolean moreMethodsOutlined;
  1141         boolean moreMethodsOutlined;
  1141         String originalMethodName = getName();
  1142         String originalMethodName = getName();
  1152         // Loop until the original method comes in under the JVM limit or
  1153         // Loop until the original method comes in under the JVM limit or
  1153         // the loop was unable to outline any more methods
  1154         // the loop was unable to outline any more methods
  1154         do {
  1155         do {
  1155             // Get all the best candidates for outlining, and sort them in
  1156             // Get all the best candidates for outlining, and sort them in
  1156             // ascending order of size
  1157             // ascending order of size
  1157             ArrayList candidateChunks = getCandidateChunks(classGen,
  1158             List<Chunk> candidateChunks = getCandidateChunks(classGen,
  1158                                                            currentMethodSize);
  1159                                                            currentMethodSize);
  1159             Collections.sort(candidateChunks);
  1160             Collections.sort(candidateChunks);
  1160 
  1161 
  1161             moreMethodsOutlined = false;
  1162             moreMethodsOutlined = false;
  1162 
  1163 
  1350 
  1351 
  1351         // Keeps track of the mapping from instruction handles in the old
  1352         // Keeps track of the mapping from instruction handles in the old
  1352         // method to instruction handles in the outlined method.  Only need
  1353         // method to instruction handles in the outlined method.  Only need
  1353         // to track instructions that are targeted by something else in the
  1354         // to track instructions that are targeted by something else in the
  1354         // generated BCEL
  1355         // generated BCEL
  1355         HashMap targetMap   = new HashMap();
  1356         HashMap<InstructionHandle, InstructionHandle> targetMap = new HashMap<>();
  1356 
  1357 
  1357         // Keeps track of the mapping from local variables in the old method
  1358         // Keeps track of the mapping from local variables in the old method
  1358         // to local variables in the outlined method.
  1359         // to local variables in the outlined method.
  1359         HashMap localVarMap = new HashMap();
  1360         HashMap<LocalVariableGen, LocalVariableGen> localVarMap = new HashMap<>();
  1360 
  1361 
  1361         HashMap revisedLocalVarStart = new HashMap();
  1362         HashMap<LocalVariableGen, InstructionHandle> revisedLocalVarStart = new HashMap<>();
  1362         HashMap revisedLocalVarEnd = new HashMap();
  1363         HashMap<LocalVariableGen, InstructionHandle> revisedLocalVarEnd = new HashMap<>();
  1363 
  1364 
  1364         // Pass 1: Make copies of all instructions, append them to the new list
  1365         // Pass 1: Make copies of all instructions, append them to the new list
  1365         // and associate old instruction references with the new ones, i.e.,
  1366         // and associate old instruction references with the new ones, i.e.,
  1366         // a 1:1 mapping.  The special marker instructions are not copied.
  1367         // a 1:1 mapping.  The special marker instructions are not copied.
  1367         // Also, identify local variables whose values need to be copied into or
  1368         // Also, identify local variables whose values need to be copied into or
  1413                     int oldLocalVarIndex = lvi.getIndex();
  1414                     int oldLocalVarIndex = lvi.getIndex();
  1414                     LocalVariableGen oldLVG =
  1415                     LocalVariableGen oldLVG =
  1415                             getLocalVariableRegistry()
  1416                             getLocalVariableRegistry()
  1416                                 .lookupRegisteredLocalVariable(oldLocalVarIndex,
  1417                                 .lookupRegisteredLocalVariable(oldLocalVarIndex,
  1417                                                               ih.getPosition());
  1418                                                               ih.getPosition());
  1418                     LocalVariableGen newLVG =
  1419                     LocalVariableGen newLVG = localVarMap.get(oldLVG);
  1419                             (LocalVariableGen)localVarMap.get(oldLVG);
       
  1420 
  1420 
  1421                     // Has the code already mapped this local variable to a
  1421                     // Has the code already mapped this local variable to a
  1422                     // local in the new method?
  1422                     // local in the new method?
  1423                     if (localVarMap.get(oldLVG) == null) {
  1423                     if (localVarMap.get(oldLVG) == null) {
  1424                         // Determine whether the local variable needs to be
  1424                         // Determine whether the local variable needs to be
  1572                 BranchInstruction bc      = (BranchInstruction)c;
  1572                 BranchInstruction bc      = (BranchInstruction)c;
  1573                 BranchInstruction bi      = (BranchInstruction)i;
  1573                 BranchInstruction bi      = (BranchInstruction)i;
  1574                 InstructionHandle itarget = bi.getTarget(); // old target
  1574                 InstructionHandle itarget = bi.getTarget(); // old target
  1575 
  1575 
  1576                 // New target must be in targetMap
  1576                 // New target must be in targetMap
  1577                 InstructionHandle newTarget =
  1577                 InstructionHandle newTarget = targetMap.get(itarget);
  1578                     (InstructionHandle)targetMap.get(itarget);
       
  1579 
  1578 
  1580                 bc.setTarget(newTarget);
  1579                 bc.setTarget(newTarget);
  1581 
  1580 
  1582                 // Handle LOOKUPSWITCH or TABLESWITCH which may have many
  1581                 // Handle LOOKUPSWITCH or TABLESWITCH which may have many
  1583                 // target instructions
  1582                 // target instructions
  1585                     InstructionHandle[] itargets = ((Select)bi).getTargets();
  1584                     InstructionHandle[] itargets = ((Select)bi).getTargets();
  1586                     InstructionHandle[] ctargets = ((Select)bc).getTargets();
  1585                     InstructionHandle[] ctargets = ((Select)bc).getTargets();
  1587 
  1586 
  1588                     // Update all targets
  1587                     // Update all targets
  1589                     for (int j=0; j < itargets.length; j++) {
  1588                     for (int j=0; j < itargets.length; j++) {
  1590                         ctargets[j] =
  1589                         ctargets[j] = targetMap.get(itargets[j]);
  1591                             (InstructionHandle)targetMap.get(itargets[j]);
       
  1592                     }
  1590                     }
  1593                 }
  1591                 }
  1594             }  else if (i instanceof LocalVariableInstruction
  1592             }  else if (i instanceof LocalVariableInstruction
  1595                             || i instanceof RET) {
  1593                             || i instanceof RET) {
  1596                 // For any instruction that touches a local variable,
  1594                 // For any instruction that touches a local variable,
  1600                 int oldLocalVarIndex = lvi.getIndex();
  1598                 int oldLocalVarIndex = lvi.getIndex();
  1601                 LocalVariableGen oldLVG =
  1599                 LocalVariableGen oldLVG =
  1602                         getLocalVariableRegistry()
  1600                         getLocalVariableRegistry()
  1603                                 .lookupRegisteredLocalVariable(oldLocalVarIndex,
  1601                                 .lookupRegisteredLocalVariable(oldLocalVarIndex,
  1604                                                               ih.getPosition());
  1602                                                               ih.getPosition());
  1605                 LocalVariableGen newLVG =
  1603                 LocalVariableGen newLVG = localVarMap.get(oldLVG);
  1606                         (LocalVariableGen)localVarMap.get(oldLVG);
       
  1607                 int newLocalVarIndex;
  1604                 int newLocalVarIndex;
  1608 
  1605 
  1609                 if (newLVG == null) {
  1606                 if (newLVG == null) {
  1610                     // Create new variable based on old variable - use same
  1607                     // Create new variable based on old variable - use same
  1611                     // name and type, but we will let the variable be active
  1608                     // name and type, but we will let the variable be active
  1643                 for (int idx = 0; idx < targeters.length; idx++) {
  1640                 for (int idx = 0; idx < targeters.length; idx++) {
  1644                     InstructionTargeter targeter = targeters[idx];
  1641                     InstructionTargeter targeter = targeters[idx];
  1645 
  1642 
  1646                     if (targeter instanceof LocalVariableGen
  1643                     if (targeter instanceof LocalVariableGen
  1647                             && ((LocalVariableGen)targeter).getEnd()==ih) {
  1644                             && ((LocalVariableGen)targeter).getEnd()==ih) {
  1648                         Object newLVG = localVarMap.get(targeter);
  1645                         LocalVariableGen newLVG = localVarMap.get(targeter);
  1649                         if (newLVG != null) {
  1646                         if (newLVG != null) {
  1650                             outlinedMethodGen.removeLocalVariable(
  1647                             outlinedMethodGen.removeLocalVariable(newLVG);
  1651                                                   (LocalVariableGen)newLVG);
       
  1652                         }
  1648                         }
  1653                     }
  1649                     }
  1654                 }
  1650                 }
  1655             }
  1651             }
  1656 
  1652 
  1665         }
  1661         }
  1666 
  1662 
  1667         // POP the reference to the CopyLocals object from the stack
  1663         // POP the reference to the CopyLocals object from the stack
  1668         oldMethCopyOutIL.append(InstructionConst.POP);
  1664         oldMethCopyOutIL.append(InstructionConst.POP);
  1669 
  1665 
  1670         // Now that the generation of the outlined code is complete, update
  1666         for (Map.Entry<LocalVariableGen, InstructionHandle> lvgRangeStartPair :
  1671         // the old local variables with new start and end ranges, as required.
  1667                 revisedLocalVarStart.entrySet()) {
  1672         Iterator revisedLocalVarStartPairIter = revisedLocalVarStart.entrySet()
  1668             LocalVariableGen lvg = lvgRangeStartPair.getKey();
  1673                                                                     .iterator();
  1669             InstructionHandle startInst = lvgRangeStartPair.getValue();
  1674         while (revisedLocalVarStartPairIter.hasNext()) {
       
  1675             Map.Entry lvgRangeStartPair =
       
  1676                     (Map.Entry)revisedLocalVarStartPairIter.next();
       
  1677             LocalVariableGen lvg = (LocalVariableGen)lvgRangeStartPair.getKey();
       
  1678             InstructionHandle startInst =
       
  1679                     (InstructionHandle)lvgRangeStartPair.getValue();
       
  1680 
  1670 
  1681             lvg.setStart(startInst);
  1671             lvg.setStart(startInst);
  1682 
  1672         }
  1683         }
  1673 
  1684 
  1674         for (Map.Entry<LocalVariableGen, InstructionHandle> lvgRangeEndPair :
  1685         Iterator revisedLocalVarEndPairIter = revisedLocalVarEnd.entrySet()
  1675                 revisedLocalVarEnd.entrySet()) {
  1686                                                                 .iterator();
  1676             LocalVariableGen lvg = lvgRangeEndPair.getKey();
  1687         while (revisedLocalVarEndPairIter.hasNext()) {
  1677             InstructionHandle endInst = lvgRangeEndPair.getValue();
  1688             Map.Entry lvgRangeEndPair =
       
  1689                     (Map.Entry)revisedLocalVarEndPairIter.next();
       
  1690             LocalVariableGen lvg = (LocalVariableGen)lvgRangeEndPair.getKey();
       
  1691             InstructionHandle endInst =
       
  1692                     (InstructionHandle)lvgRangeEndPair.getValue();
       
  1693 
  1678 
  1694             lvg.setEnd(endInst);
  1679             lvg.setEnd(endInst);
  1695         }
  1680         }
  1696 
  1681 
  1697         xsltc.dumpClass(copyAreaCG.getJavaClass());
  1682         xsltc.dumpClass(copyAreaCG.getJavaClass());