InstructionFinder.java revision 286
286N/A * reserved comment block 286N/A * DO NOT REMOVE OR ALTER! 286N/A/* ==================================================================== 286N/A * The Apache Software License, Version 1.1 286N/A * Copyright (c) 2001 The Apache Software Foundation. All rights 286N/A * Redistribution and use in source and binary forms, with or without 286N/A * modification, are permitted provided that the following conditions 286N/A * 1. Redistributions of source code must retain the above copyright 286N/A * notice, this list of conditions and the following disclaimer. 286N/A * 2. Redistributions in binary form must reproduce the above copyright 286N/A * notice, this list of conditions and the following disclaimer in 286N/A * the documentation and/or other materials provided with the 286N/A * 3. The end-user documentation included with the redistribution, 286N/A * if any, must include the following acknowledgment: 286N/A * "This product includes software developed by the 286N/A * Alternately, this acknowledgment may appear in the software itself, 286N/A * if and wherever such third-party acknowledgments normally appear. 286N/A * 4. The names "Apache" and "Apache Software Foundation" and 286N/A * "Apache BCEL" must not be used to endorse or promote products 286N/A * derived from this software without prior written permission. For 286N/A * written permission, please contact apache@apache.org. 286N/A * 5. Products derived from this software may not be called "Apache", 286N/A * "Apache BCEL", nor may "Apache" appear in their name, without 286N/A * prior written permission of the Apache Software Foundation. 286N/A * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 286N/A * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 286N/A * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 286N/A * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR 286N/A * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 286N/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 286N/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 286N/A * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 286N/A * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 286N/A * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 286N/A * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 286N/A * ==================================================================== 286N/A * This software consists of voluntary contributions made by many 286N/A * individuals on behalf of the Apache Software Foundation. For more 286N/A * information on the Apache Software Foundation, please see 286N/A * InstructionFinder is a tool to search for given instructions patterns, 286N/A * i.e., match sequences of instructions in an instruction list via 286N/A * regular expressions. This can be used, e.g., in order to implement 286N/A * a peep hole optimizer that looks for code patterns and replaces 286N/A * them with faster equivalents. 286N/A * Regexp</a> package to search for regular expressions. 286N/A * A typical application would look like this: 286N/A InstructionFinder f = new InstructionFinder(il); 286N/A String pat = "IfInstruction ICONST_0 GOTO ICONST_1 NOP (IFEQ|IFNE)"; 286N/A for(Iterator i = f.search(pat, constraint); i.hasNext(); ) { 286N/A InstructionHandle[] match = (InstructionHandle[])i.next(); 286N/A il.delete(match[1], match[5]); 286N/A private static final int OFFSET =
32767;
// char + OFFSET is outside of LATIN-1 286N/A private static final int NO_OPCODES =
256;
// Potential number, some are not used 286N/A * @param il instruction list to search for given patterns 286N/A * Reread the instruction list, e.g., after you've altered the list upon a match. 286N/A char[]
buf =
new char[
size];
// Create a string with length equal to il length 286N/A // Map opcodes to characters 286N/A * Map symbolic instruction names like "getfield" to a single character. 286N/A * @param pattern instruction pattern in lower case 286N/A * @return encoded string for a pattern such as "BranchInstruction". 286N/A * Replace symbolic names of instructions with the appropiate character and remove 286N/A * all white space from string. Meta characters such as +, * are ignored. 286N/A * @param pattern The pattern to compile 286N/A * @return translated regular expression string 286N/A * @return the matched piece of code as an array of instruction (handles) 286N/A * Search for the given pattern in the instruction list. You can search for any valid 286N/A * opcode via its symbolic name, e.g. "istore". You can also use a super class or 286N/A * an interface name to match a whole set of instructions, e.g. "BranchInstruction" or 286N/A * "LoadInstruction". "istore" is also an alias for all "istore_x" instructions. Additional 286N/A * aliases are "if" for "ifxx", "if_icmp" for "if_icmpxx", "if_acmp" for "if_acmpxx". 286N/A * Consecutive instruction names must be separated by white space which will be removed 286N/A * during the compilation of the pattern. 286N/A * For the rest the usual pattern matching rules for regular expressions apply.<P> 286N/A search("BranchInstruction NOP ((IfInstruction|GOTO)+ ISTORE Instruction)*"); 286N/A * <p>If you alter the instruction list upon a match such that other 286N/A * matching areas are affected, you should call reread() to update 286N/A * the finder and call search() again, because the matches are cached. 286N/A * @param pattern the instruction pattern to search for, where case is ignored 286N/A * @param from where to start the search in the instruction list 286N/A * @param constraint optional CodeConstraint to check the found code pattern for 286N/A * user-defined constraints 286N/A * @return iterator of matches where e.nextElement() returns an array of instruction handles 286N/A * describing the matched area 286N/A start = i;
// Where to start search from (index) 286N/A " not found in instruction list.");
286N/A * Start search beginning from the start of the given instruction list. 286N/A * @param pattern the instruction pattern to search for, where case is ignored 286N/A * @return iterator of matches where e.nextElement() 286N/A * returns an array of instruction handles describing the matched 286N/A * Start search beginning from `from'. 286N/A * @param pattern the instruction pattern to search for, where case is ignored 286N/A * @param from where to start the search in the instruction list 286N/A * @return iterator of matches where e.nextElement() returns an array of instruction handles 286N/A * describing the matched area 286N/A * Start search beginning from the start of the given instruction list. 286N/A * Check found matches with the constraint object. 286N/A * @param pattern the instruction pattern to search for, case is ignored 286N/A * @param constraint constraints to be checked on matching code 286N/A * @return instruction handle or `null' if the match failed 286N/A * Convert opcode number to char. 286N/A * @return the inquired instruction list 286N/A * Code patterns found may be checked using an additional 286N/A * user-defined constraint object whether they really match the needed criterion. 286N/A * I.e., check constraints that can not expressed with regular expressions. 286N/A * @param match array of instructions matching the requested pattern 286N/A * @return true if the matched area is really useful 286N/A // Initialize pattern map 286N/A map.
put(
"arithmeticinstruction",
"(irem|lrem|iand|ior|ineg|isub|lneg|fneg|fmul|ldiv|fadd|lxor|frem|idiv|land|ixor|ishr|fsub|lshl|fdiv|iadd|lor|dmul|lsub|ishl|imul|lmul|lushr|dneg|iushr|lshr|ddiv|drem|dadd|ladd|dsub)");
286N/A map.
put(
"invokeinstruction",
"(invokevirtual|invokeinterface|invokestatic|invokespecial)");
286N/A map.
put(
"arrayinstruction",
"(baload|aastore|saload|caload|fastore|lastore|iaload|castore|iastore|aaload|bastore|sastore|faload|laload|daload|dastore)");
286N/A map.
put(
"conversioninstruction",
"(d2l|l2d|i2s|d2i|l2i|i2b|l2f|d2f|f2i|i2d|i2l|f2d|i2c|f2l|i2f)");
286N/A map.
put(
"localvariableinstruction",
"(fstore|iinc|lload|dstore|dload|iload|aload|astore|istore|fload|lstore)");
286N/A map.
put(
"loadinstruction",
"(fload|dload|lload|iload|aload)");
286N/A map.
put(
"fieldinstruction",
"(getfield|putstatic|getstatic|putfield)");
286N/A map.
put(
"cpinstruction",
"(ldc2_w|invokeinterface|multianewarray|putstatic|instanceof|getstatic|checkcast|getfield|invokespecial|ldc_w|invokestatic|invokevirtual|putfield|ldc|new|anewarray)");
286N/A map.
put(
"stackinstruction",
"(dup2|swap|dup2_x2|pop|pop2|dup|dup2_x1|dup_x2|dup_x1)");
286N/A map.
put(
"branchinstruction",
"(ifle|if_acmpne|if_icmpeq|if_acmpeq|ifnonnull|goto_w|iflt|ifnull|if_icmpne|tableswitch|if_icmple|ifeq|if_icmplt|jsr_w|if_icmpgt|ifgt|jsr|goto|ifne|ifge|lookupswitch|if_icmpge)");
286N/A map.
put(
"returninstruction",
"(lreturn|ireturn|freturn|dreturn|areturn|return)");
286N/A map.
put(
"storeinstruction",
"(istore|fstore|dstore|astore|lstore)");
286N/A map.
put(
"ifinstruction",
"(ifeq|ifgt|if_icmpne|if_icmpeq|ifge|ifnull|ifne|if_icmple|if_icmpge|if_acmpeq|if_icmplt|if_acmpne|ifnonnull|iflt|if_icmpgt|ifle)");
286N/A map.
put(
"variablelengthinstruction",
"(tableswitch|jsr|goto|lookupswitch)");
286N/A map.
put(
"unconditionalbranch",
"(goto|jsr|jsr_w|athrow|goto_w)");
286N/A map.
put(
"constantpushinstruction",
"(dconst|bipush|sipush|fconst|iconst|lconst)");
286N/A map.
put(
"typedinstruction",
"(imul|lsub|aload|fload|lor|new|aaload|fcmpg|iand|iaload|lrem|idiv|d2l|isub|dcmpg|dastore|ret|f2d|f2i|drem|iinc|i2c|checkcast|frem|lreturn|astore|lushr|daload|dneg|fastore|istore|lshl|ldiv|lstore|areturn|ishr|ldc_w|invokeinterface|aastore|lxor|ishl|l2d|i2f|return|faload|sipush|iushr|caload|instanceof|invokespecial|putfield|fmul|ireturn|laload|d2f|lneg|ixor|i2l|fdiv|lastore|multianewarray|i2b|getstatic|i2d|putstatic|fcmpl|saload|ladd|irem|dload|jsr_w|dconst|dcmpl|fsub|freturn|ldc|aconst_null|castore|lmul|ldc2_w|dadd|iconst|f2l|ddiv|dstore|land|jsr|anewarray|dmul|bipush|dsub|sastore|d2i|i2s|lshr|iadd|l2i|lload|bastore|fstore|fneg|iload|fadd|baload|fconst|ior|ineg|dreturn|l2f|lconst|getfield|invokevirtual|invokestatic|iastore)");
286N/A map.
put(
"popinstruction",
"(fstore|dstore|pop|pop2|astore|putstatic|istore|lstore)");
286N/A map.
put(
"allocationinstruction",
"(multianewarray|new|anewarray|newarray)");
286N/A map.
put(
"indexedinstruction",
"(lload|lstore|fload|ldc2_w|invokeinterface|multianewarray|astore|dload|putstatic|instanceof|getstatic|checkcast|getfield|invokespecial|dstore|istore|iinc|ldc_w|ret|fstore|invokestatic|iload|putfield|invokevirtual|ldc|new|aload|anewarray)");
286N/A map.
put(
"pushinstruction",
"(dup|lload|dup2|bipush|fload|ldc2_w|sipush|lconst|fconst|dload|getstatic|ldc_w|aconst_null|dconst|iload|ldc|iconst|aload)");
286N/A map.
put(
"stackproducer",
"(imul|lsub|aload|fload|lor|new|aaload|fcmpg|iand|iaload|lrem|idiv|d2l|isub|dcmpg|dup|f2d|f2i|drem|i2c|checkcast|frem|lushr|daload|dneg|lshl|ldiv|ishr|ldc_w|invokeinterface|lxor|ishl|l2d|i2f|faload|sipush|iushr|caload|instanceof|invokespecial|fmul|laload|d2f|lneg|ixor|i2l|fdiv|getstatic|i2b|swap|i2d|dup2|fcmpl|saload|ladd|irem|dload|jsr_w|dconst|dcmpl|fsub|ldc|arraylength|aconst_null|tableswitch|lmul|ldc2_w|iconst|dadd|f2l|ddiv|land|jsr|anewarray|dmul|bipush|dsub|d2i|newarray|i2s|lshr|iadd|lload|l2i|fneg|iload|fadd|baload|fconst|lookupswitch|ior|ineg|lconst|l2f|getfield|invokevirtual|invokestatic)");
286N/A map.
put(
"stackconsumer",
"(imul|lsub|lor|iflt|fcmpg|if_icmpgt|iand|ifeq|if_icmplt|lrem|ifnonnull|idiv|d2l|isub|dcmpg|dastore|if_icmpeq|f2d|f2i|drem|i2c|checkcast|frem|lreturn|astore|lushr|pop2|monitorexit|dneg|fastore|istore|lshl|ldiv|lstore|areturn|if_icmpge|ishr|monitorenter|invokeinterface|aastore|lxor|ishl|l2d|i2f|return|iushr|instanceof|invokespecial|fmul|ireturn|d2f|lneg|ixor|pop|i2l|ifnull|fdiv|lastore|i2b|if_acmpeq|ifge|swap|i2d|putstatic|fcmpl|ladd|irem|dcmpl|fsub|freturn|ifgt|castore|lmul|dadd|f2l|ddiv|dstore|land|if_icmpne|if_acmpne|dmul|dsub|sastore|ifle|d2i|i2s|lshr|iadd|l2i|bastore|fstore|fneg|fadd|ior|ineg|ifne|dreturn|l2f|if_icmple|getfield|invokevirtual|invokestatic|iastore)");
286N/A map.
put(
"exceptionthrower",
"(irem|lrem|laload|putstatic|baload|dastore|areturn|getstatic|ldiv|anewarray|iastore|castore|idiv|saload|lastore|fastore|putfield|lreturn|caload|getfield|return|aastore|freturn|newarray|instanceof|multianewarray|athrow|faload|iaload|aaload|dreturn|monitorenter|checkcast|bastore|arraylength|new|invokevirtual|sastore|ldc_w|ireturn|invokespecial|monitorexit|invokeinterface|ldc|invokestatic|daload)");
286N/A map.
put(
"loadclass",
"(multianewarray|invokeinterface|instanceof|invokespecial|putfield|checkcast|putstatic|invokevirtual|new|getstatic|invokestatic|getfield|anewarray)");
286N/A map.
put(
"instructiontargeter",
"(ifle|if_acmpne|if_icmpeq|if_acmpeq|ifnonnull|goto_w|iflt|ifnull|if_icmpne|tableswitch|if_icmple|ifeq|if_icmplt|jsr_w|if_icmpgt|ifgt|jsr|goto|ifne|ifge|lookupswitch|if_icmpge)");
286N/A map.
put(
"if_icmp",
"(if_icmpne|if_icmpeq|if_icmple|if_icmpge|if_icmplt|if_icmpgt)");
286N/A // Precompile some aliases first 286N/A // Add instruction alias to match anything 286N/A * Internal debugging routines.