signature:
public class ConfigFileLexer { /** * Scan all characters from the input stream and generate a corresponding
 * list of tokens , whilst discarding all whitespace and comments .
 * @ return */
public List < Token > scan ( ) { } }

implementation: ArrayList < Token > tokens = new ArrayList < > ( ) ; pos = 0 ; while ( pos < input . length ( ) ) { char c = input . charAt ( pos ) ; if ( Character . isDigit ( c ) ) { tokens . add ( scanNumericConstant ( ) ) ; } else if ( c == '"' ) { tokens . add ( scanStringConstant ( ) ) ; } else if ( c == '\'' ) { tokens . add ( scanCharacterConstant ( ) ) ; } else if ( isOperatorStart ( c ) ) { tokens . add ( scanOperator ( ) ) ; } else if ( Character . isLetter ( c ) || c == '_' ) { tokens . add ( scanIdentifier ( ) ) ; } else if ( Character . isWhitespace ( c ) ) { scanWhiteSpace ( tokens ) ; } else { syntaxError ( "unknown token encountered" , pos ) ; } } return tokens ;


signature:
public class ConfigFileLexer { /** * Scan a numeric constant . That is a sequence of digits which gives either
 * an integer constant , or a real constant ( if it includes a dot ) or a byte
 * ( if it ends in a ' b ' ) .
 * @ return */
public Token scanNumericConstant ( ) { } }

implementation: int start = pos ; while ( pos < input . length ( ) && Character . isDigit ( input . charAt ( pos ) ) ) { pos = pos + 1 ; } return new Token ( Token . Kind . IntValue , input . substring ( start , pos ) , start ) ;


signature:
public class ConfigFileLexer { /** * Scan a character constant , such as e . g . ' c ' . Observe that care must be
 * taken to properly handle escape codes . For example , ' \ n ' is a single
 * character constant which is made up from two characters in the input
 * string .
 * @ return */
public Token scanCharacterConstant ( ) { } }

implementation:
int start = pos ; pos ++ ; char c = input . charAt ( pos ++ ) ; if ( c == '\\' ) { // escape code
switch ( input . charAt ( pos ++ ) ) { case 'b' : c = '\b' ; break ; case 't' : c = '\t' ; break ; case 'n' : c = '\n' ; break ; case 'f' : c = '\f' ; break ; case 'r' : c = '\r' ; break ; case '"' : c = '\"' ; break ; case '\'' : c = '\'' ; break ; case '\\' : c = '\\' ; break ; default : syntaxError ( "unrecognised escape character" , pos ) ; } } if ( input . charAt ( pos ) != '\'' ) { syntaxError ( "unexpected end-of-character" , pos ) ; } pos = pos + 1 ; return new Token ( Token . Kind . CharValue , input . substring ( start , pos ) , start ) ;


signature:
public class ConfigFileLexer { /** * Raise a syntax error with a given message at given index .
 * @ param msg
 * - - - message to raise .
 * @ param index
 * - - - index position to associate the error with . */
private void syntaxError ( String msg , int index ) { } }

implementation:
// FIXME : this is clearly not a sensible approach
throw new SyntacticException ( msg , entry , new ConfigFile . Attribute . Span ( null , index , index ) ) ;


signature:
public class AbstractFolder { /** * Insert a newly created item into this folder . Observe we assume
 * < code > entry . id ( ) . parent ( ) = = id < / code > .
 * @ param item */
protected void insert ( Path . Item item ) throws IOException { } }

implementation:
if ( item . id ( ) . parent ( ) != id ) { throw new IllegalArgumentException ( "Cannot insert with incorrect Path.Item (" + item . id ( ) + ") into AbstractFolder (" + id + ")" ) ; } updateContents ( ) ; Path . ID id = item . id ( ) ; int index = binarySearch ( contents , nentries , id ) ; if ( index < 0 ) { index = - index - 1 ; // calculate insertion point
} else { // indicates already an entry with a different content type
} // Insert item at given index
insert ( index , item ) ;


signature:
public class SimpleLog { /** * Log a message to System . out . The message is prepended with the current indentation string . The
 * indentation is only applied at the start of the message , not for every line break within the
 * message .
 * @ param format format string for message
 * @ param args values to be substituted into format */
@ FormatMethod public void log ( String format , @ Nullable Object ... args ) { } }

implementation: if ( enabled ) { System . out . print ( getIndentString ( ) ) ; System . out . printf ( format , args ) ; }


signature:
public class SimpleLog { /** * Print a stack trace to System . out . */
public void logStackTrace ( ) { } }

implementation: if ( enabled ) { Throwable t = new Throwable ( ) ; t . fillInStackTrace ( ) ; StackTraceElement [ ] ste_arr = t . getStackTrace ( ) ; for ( int ii = 2 ; ii < ste_arr . length ; ii ++ ) { StackTraceElement ste = ste_arr [ ii ] ; System . out . printf ( "%s  %s%n" , getIndentString ( ) , ste ) ; } }


signature:
public class SimpleLog { /** * Return the current indentation string . */
private String getIndentString ( ) { } }

implementation: assert enabled ; if ( indentString == null ) { for ( int i = indentStrings . size ( ) ; i <= indentLevel ; i ++ ) { indentStrings . add ( indentStrings . get ( i - 1 ) + INDENT_STR_ONE_LEVEL ) ; } indentString = indentStrings . get ( indentLevel ) ; } return indentString ;


signature:
public class StackVer { /** * Whenever the outgoing frame situation of an InstructionContext changes , all its successors are
 * put [ back ] into the queue [ as if they were unvisited ] . The proof of termination is about the
 * existence of a fix point of frame merging . */
private void circulationPump ( final MethodGen m , final ControlFlowGraph cfg , final InstructionContext start , final Frame vanillaFrame , final InstConstraintVisitor icv , final ExecutionVisitor ev ) { } }

implementation:
final Random random = new Random ( ) ; final InstructionContextQueue icq = new InstructionContextQueue ( ) ; execute ( start , vanillaFrame , new ArrayList < InstructionContext > ( ) , icv , ev ) ; // new ArrayList ( ) < = > no Instruction was executed before
// = > Top - Level routine ( no jsr call before )
icq . add ( start , new ArrayList < InstructionContext > ( ) ) ; // LOOP !
while ( ! icq . isEmpty ( ) ) { InstructionContext u ; ArrayList < InstructionContext > ec ; if ( ! DEBUG ) { final int r = random . nextInt ( icq . size ( ) ) ; u = icq . getIC ( r ) ; ec = icq . getEC ( r ) ; icq . remove ( r ) ; } else { u = icq . getIC ( 0 ) ; ec = icq . getEC ( 0 ) ; icq . remove ( 0 ) ; } @ SuppressWarnings ( "unchecked" ) // ec is of type ArrayList < InstructionContext >
final ArrayList < InstructionContext > oldchain = ( ArrayList < InstructionContext > ) ( ec . clone ( ) ) ; @ SuppressWarnings ( "unchecked" ) // ec is of type ArrayList < InstructionContext >
final ArrayList < InstructionContext > newchain = ( ArrayList < InstructionContext > ) ( ec . clone ( ) ) ; newchain . add ( u ) ; if ( ( u . getInstruction ( ) . getInstruction ( ) ) instanceof RET ) { // System . err . println ( u ) ;
// We can only follow _ one _ successor , the one after the
// JSR that was recently executed .
final RET ret = ( RET ) ( u . getInstruction ( ) . getInstruction ( ) ) ; final ReturnaddressType t = ( ReturnaddressType ) u . getOutFrame ( oldchain ) . getLocals ( ) . get ( ret . getIndex ( ) ) ; final InstructionContext theSuccessor = cfg . contextOf ( t . getTarget ( ) ) ; // Sanity check
InstructionContext lastJSR = null ; int skip_jsr = 0 ; for ( int ss = oldchain . size ( ) - 1 ; ss >= 0 ; ss -- ) { if ( skip_jsr < 0 ) { throw new AssertionViolatedException ( "More RET than JSR in execution chain?!" ) ; } // System . err . println ( " + " + oldchain . get ( ss ) ) ;
if ( ( oldchain . get ( ss ) ) . getInstruction ( ) . getInstruction ( ) instanceof JsrInstruction ) { if ( skip_jsr == 0 ) { lastJSR = oldchain . get ( ss ) ; break ; } skip_jsr -- ; } if ( ( oldchain . get ( ss ) ) . getInstruction ( ) . getInstruction ( ) instanceof RET ) { skip_jsr ++ ; } } if ( lastJSR == null ) { throw new AssertionViolatedException ( "RET without a JSR before in ExecutionChain?! EC: '" + oldchain + "'." ) ; } final JsrInstruction jsr = ( JsrInstruction ) ( lastJSR . getInstruction ( ) . getInstruction ( ) ) ; if ( theSuccessor != ( cfg . contextOf ( jsr . physicalSuccessor ( ) ) ) ) { throw new AssertionViolatedException ( "RET '" + u . getInstruction ( ) + "' info inconsistent: jump back to '" + theSuccessor + "' or '" + cfg . contextOf ( jsr . physicalSuccessor ( ) ) + "'?" ) ; } if ( execute ( theSuccessor , u . getOutFrame ( oldchain ) , newchain , icv , ev ) ) { @ SuppressWarnings ( "unchecked" ) // newchain is already of type ArrayList < InstructionContext >
final ArrayList < InstructionContext > newchainClone = ( ArrayList < InstructionContext > ) newchain . clone ( ) ; icq . add ( theSuccessor , newchainClone ) ; } } else { // " not a ret "
// Normal successors . Add them to the queue of successors .
final InstructionContext [ ] succs = u . getSuccessors ( ) ; for ( final InstructionContext v : succs ) { if ( execute ( v , u . getOutFrame ( oldchain ) , newchain , icv , ev ) ) { @ SuppressWarnings ( "unchecked" ) // newchain is already of type ArrayList < InstructionContext >
final ArrayList < InstructionContext > newchainClone = ( ArrayList < InstructionContext > ) newchain . clone ( ) ; icq . add ( v , newchainClone ) ; } } } // end " not a ret "
// Exception Handlers . Add them to the queue of successors .
// [ subroutines are never protected ; mandated by JustIce ]
final ExceptionHandler [ ] exc_hds = u . getExceptionHandlers ( ) ; for ( final ExceptionHandler exc_hd : exc_hds ) { final InstructionContext v = cfg . contextOf ( exc_hd . getHandlerStart ( ) ) ; // TODO : the " oldchain " and " newchain " is used to determine the subroutine
// we ' re in ( by searching for the last JSR ) by the InstructionContext
// implementation . Therefore , we should not use this chain mechanism
// when dealing with exception handlers .
// Example : a JSR with an exception handler as its successor does not
// mean we ' re in a subroutine if we go to the exception handler .
// We should address this problem later ; by now we simply " cut " the chain
// by using an empty chain for the exception handlers .
// if ( execute ( v , new Frame ( u . getOutFrame ( oldchain ) . getLocals ( ) ,
// new OperandStack ( u . getOutFrame ( ) . getStack ( ) . maxStack ( ) ,
// ( exc _ hds [ s ] . getExceptionType ( ) = = null ? Type . THROWABLE : exc _ hds [ s ] . getExceptionType ( ) ) ) ) ,
// newchain ) , icv , ev ) {
// icq . add ( v , ( ArrayList ) newchain . clone ( ) ) ;
if ( execute ( v , new Frame ( u . getOutFrame ( oldchain ) . getLocals ( ) , new OperandStack ( u . getOutFrame ( oldchain ) . getStack ( ) . maxStack ( ) , exc_hd . getExceptionType ( ) == null ? Type . THROWABLE : exc_hd . getExceptionType ( ) ) ) , new ArrayList < InstructionContext > ( ) , icv , ev ) ) { icq . add ( v , new ArrayList < InstructionContext > ( ) ) ; } } } // while ( ! icq . isEmpty ( ) ) END
InstructionHandle ih = start . getInstruction ( ) ; do { if ( ( ih . getInstruction ( ) instanceof ReturnInstruction ) && ( ! ( cfg . isDead ( ih ) ) ) ) { final InstructionContext ic = cfg . contextOf ( ih ) ; // TODO : This is buggy , we check only the top - level return instructions this way .
// Maybe some maniac returns from a method when in a subroutine ?
final Frame f = ic . getOutFrame ( new ArrayList < InstructionContext > ( ) ) ; final LocalVariables lvs = f . getLocals ( ) ; for ( int i = 0 ; i < lvs . maxLocals ( ) ; i ++ ) { if ( lvs . get ( i ) instanceof UninitializedObjectType ) { this . addMessage ( "Warning: ReturnInstruction '" + ic + "' may leave method with an uninitialized object in the local variables array '" + lvs + "'." ) ; } } final OperandStack os = f . getStack ( ) ; for ( int i = 0 ; i < os . size ( ) ; i ++ ) { if ( os . peek ( i ) instanceof UninitializedObjectType ) { this . addMessage ( "Warning: ReturnInstruction '" + ic + "' may leave method with an uninitialized object on the operand stack '" + os + "'." ) ; } } /* This code from Pass3bVerifier incorrectly fails on some valid class files .
 / / see JVM $ 4.8.2
 Type returnedType = null ;
 final OperandStack inStack = ic . getInFrame ( ) . getStack ( ) ;
 if ( inStack . size ( ) > = 1 ) {
 returnedType = inStack . peek ( ) ;
 } else {
 returnedType = Type . VOID ;
 if ( returnedType ! = null ) {
 if ( returnedType instanceof ReferenceType ) {
 try {
 if ( ! ( ( ReferenceType ) returnedType ) . isCastableTo ( m . getReturnType ( ) ) ) {
 invalidReturnTypeError ( returnedType , m ) ;
 } catch ( final ClassNotFoundException e ) {
 / / Don ' t know what do do now , so raise RuntimeException
 throw new RuntimeException ( e ) ;
 } else if ( ! returnedType . equals ( m . getReturnType ( ) . normalizeForStackOrLocal ( ) ) ) {
 invalidReturnTypeError ( returnedType , m ) ; */
} } while ( ( ih = ih . getNext ( ) ) != null ) ;


signature:
public class StackVer { /** * Pass 3b implements the data flow analysis as described in the Java Virtual Machine
 * Specification , Second Edition . Later versions will use LocalVariablesInfo objects to verify if
 * the verifier - inferred types and the class file ' s debug information ( LocalVariables attributes )
 * match [ TODO ] .
 * @ param mg MethodGen for the method to be verified
 * @ return the VerificationResult
 * @ see org . apache . bcel . verifier . statics . LocalVariablesInfo
 * @ see org . apache . bcel . verifier . statics . Pass2Verifier # getLocalVariablesInfo ( int ) */
public VerificationResult do_stack_ver ( MethodGen mg ) { } }

implementation:
/* This code is not needed for StackVer .
 if ( ! myOwner . doPass3a ( method _ no ) . equals ( VerificationResult . VR _ OK ) ) {
 return VerificationResult . VR _ NOTYET ;
 / / Pass 3a ran before , so it ' s safe to assume the JavaClass object is
 / / in the BCEL repository .
 JavaClass jc ;
 try {
 jc = Repository . lookupClass ( myOwner . getClassName ( ) ) ;
 } catch ( final ClassNotFoundException e ) {
 / / FIXME : maybe not the best way to handle this
 throw new AssertionViolatedException ( " Missing class : " + e , e ) ; */
final ConstantPoolGen constantPoolGen = mg . getConstantPool ( ) ; // Init Visitors
final InstConstraintVisitor icv = new NoConstraintsVisitor ( ) ; icv . setConstantPoolGen ( constantPoolGen ) ; final ExecutionVisitor ev = new ExecutionVisitor ( ) ; ev . setConstantPoolGen ( constantPoolGen ) ; try { stack_types = new StackTypes ( mg ) ; icv . setMethodGen ( mg ) ; // / / / / / DFA BEGINS HERE / / / / /
if ( ! ( mg . isAbstract ( ) || mg . isNative ( ) ) ) { // IF mg HAS CODE ( See pass 2)
// false says don ' t check if jsr subroutine is covered by exception handler
final ControlFlowGraph cfg = new ControlFlowGraph ( mg , false ) ; // Build the initial frame situation for this method .
final Frame f = new Frame ( mg . getMaxLocals ( ) , mg . getMaxStack ( ) ) ; if ( ! mg . isStatic ( ) ) { if ( mg . getName ( ) . equals ( Const . CONSTRUCTOR_NAME ) ) { Frame . setThis ( new UninitializedObjectType ( new ObjectType ( mg . getClassName ( ) ) ) ) ; f . getLocals ( ) . set ( 0 , Frame . getThis ( ) ) ; } else { @ SuppressWarnings ( "nullness" ) // unannotated : org . apache . bcel . verifier . structurals . Frame
@ NonNull UninitializedObjectType dummy = null ; Frame . setThis ( dummy ) ; f . getLocals ( ) . set ( 0 , new ObjectType ( mg . getClassName ( ) ) ) ; } } final Type [ ] argtypes = mg . getArgumentTypes ( ) ; int twoslotoffset = 0 ; for ( int j = 0 ; j < argtypes . length ; j ++ ) { if ( argtypes [ j ] == Type . SHORT || argtypes [ j ] == Type . BYTE || argtypes [ j ] == Type . CHAR || argtypes [ j ] == Type . BOOLEAN ) { argtypes [ j ] = Type . INT ; } f . getLocals ( ) . set ( twoslotoffset + j + ( mg . isStatic ( ) ? 0 : 1 ) , argtypes [ j ] ) ; if ( argtypes [ j ] . getSize ( ) == 2 ) { twoslotoffset ++ ; f . getLocals ( ) . set ( twoslotoffset + j + ( mg . isStatic ( ) ? 0 : 1 ) , Type . UNKNOWN ) ; } } circulationPump ( mg , cfg , cfg . contextOf ( mg . getInstructionList ( ) . getStart ( ) ) , f , icv , ev ) ; } } catch ( final VerifierConstraintViolatedException ce ) { ce . extendMessage ( "Constraint violated in method '" + mg + "':\n" , "" ) ; return new VerificationResult ( VerificationResult . VERIFIED_REJECTED , ce . getMessage ( ) ) ; } catch ( final RuntimeException re ) { // These are internal errors
final StringWriter sw = new StringWriter ( ) ; final PrintWriter pw = new PrintWriter ( sw ) ; re . printStackTrace ( pw ) ; throw new AssertionViolatedException ( "Some RuntimeException occured while verify()ing class '" + mg . getClassName ( ) + "', method '" + mg + "'. Original RuntimeException's stack trace:\n---\n" + sw + "---\n" , re ) ; } return VerificationResult . VR_OK ;


signature:
public class StackVer { /** * Like InstructionContext . execute , but also sets stack _ types . */
boolean execute ( InstructionContext ic , Frame inFrame , ArrayList < InstructionContext > executionPredecessors , InstConstraintVisitor icv , ExecutionVisitor ev ) { } }

implementation: stack_types . set ( ic . getInstruction ( ) . getPosition ( ) , inFrame ) ; return ic . execute ( inFrame , executionPredecessors , icv , ev ) ;


signature:
public class StackMapUtils { /** * Returns a String array with new _ string added to the end of arr .
 * @ param arr original string array
 * @ param new _ string string to be added
 * @ return the new string array */
protected String [ ] add_string ( String [ ] arr , String new_string ) { } }

implementation: String [ ] new_arr = new String [ arr . length + 1 ] ; for ( int ii = 0 ; ii < arr . length ; ii ++ ) { new_arr [ ii ] = arr [ ii ] ; } new_arr [ arr . length ] = new_string ; return new_arr ;


signature:
public class StackMapUtils { /** * Return the attribute name for the specified attribute .
 * @ param a the attribute
 * @ return the attribute name for the specified attribute */
@ Pure protected final String get_attribute_name ( Attribute a ) { } }

implementation: int con_index = a . getNameIndex ( ) ; Constant c = pool . getConstant ( con_index ) ; String att_name = ( ( ConstantUtf8 ) c ) . getBytes ( ) ; return att_name ;


signature:
public class StackMapUtils { /** * Find the StackMapTable attribute for a method . Return null if there isn ' t one .
 * @ param mgen the method
 * @ return the StackMapTable attribute for the method ( or null if not present ) */
@ Pure protected final @ Nullable Attribute get_stack_map_table_attribute ( MethodGen mgen ) { } }

implementation: for ( Attribute a : mgen . getCodeAttributes ( ) ) { if ( is_stack_map_table ( a ) ) { return a ; } } return null ;


signature:
public class StackMapUtils { /** * Find the LocalVariableTypeTable attribute for a method . Return null if there isn ' t one .
 * @ param mgen the method
 * @ return the LocalVariableTypeTable attribute for the method ( or null if not present ) */
@ Pure protected final @ Nullable Attribute get_local_variable_type_table_attribute ( MethodGen mgen ) { } }

implementation: for ( Attribute a : mgen . getCodeAttributes ( ) ) { if ( is_local_variable_type_table ( a ) ) { return a ; } } return null ;


signature:
public class StackMapUtils { /** * We have inserted additional byte ( s ) into the instruction list ; update the StackMaps , if
 * required . Also sets running _ offset .
 * @ param position the location of insertion
 * @ param delta the size of the insertion */
protected final void update_stack_map_offset ( int position , int delta ) { } }

implementation:
running_offset = - 1 ; // no + 1 on first entry
for ( int i = 0 ; i < stack_map_table . length ; i ++ ) { running_offset = stack_map_table [ i ] . getByteCodeOffset ( ) + running_offset + 1 ; if ( running_offset > position ) { stack_map_table [ i ] . updateByteCodeOffset ( delta ) ; // Only update the first StackMap that occurs after the given
// offset as map offsets are relative to previous map entry .
return ; } }


signature:
public class StackMapUtils { /** * Find the StackMap entry whose offset matches the input argument . Also sets running _ offset .
 * @ param offset byte code offset
 * @ return the corresponding StackMapEntry */
protected final StackMapEntry find_stack_map_equal ( int offset ) { } }

implementation:
running_offset = - 1 ; // no + 1 on first entry
for ( int i = 0 ; i < stack_map_table . length ; i ++ ) { running_offset = stack_map_table [ i ] . getByteCodeOffset ( ) + running_offset + 1 ; if ( running_offset > offset ) { throw new RuntimeException ( "Invalid StackMap offset 1" ) ; } if ( running_offset == offset ) { return stack_map_table [ i ] ; } // try next map entry
} // no offset matched
throw new RuntimeException ( "Invalid StackMap offset 2" ) ;


signature:
public class StackMapUtils { /** * Find the index of the StackMap entry whose offset is the last one before the input argument .
 * Return - 1 if there isn ' t one . Also sets running _ offset and number _ active _ locals .
 * @ param offset byte code offset
 * @ return the corresponding StackMapEntry index */
protected final int find_stack_map_index_before ( int offset ) { } }

implementation:
number_active_locals = initial_locals_count ; running_offset = - 1 ; // no + 1 on first entry
for ( int i = 0 ; i < stack_map_table . length ; i ++ ) { running_offset = running_offset + stack_map_table [ i ] . getByteCodeOffset ( ) + 1 ; if ( running_offset >= offset ) { if ( i == 0 ) { // reset offset to previous
running_offset = - 1 ; return - 1 ; } else { // back up offset to previous
running_offset = running_offset - stack_map_table [ i ] . getByteCodeOffset ( ) - 1 ; // return previous
return i - 1 ; } } // Update number of active locals based on this StackMap entry .
int frame_type = stack_map_table [ i ] . getFrameType ( ) ; if ( frame_type >= Const . APPEND_FRAME && frame_type <= Const . APPEND_FRAME_MAX ) { number_active_locals += frame_type - 251 ; } else if ( frame_type >= Const . CHOP_FRAME && frame_type <= Const . CHOP_FRAME_MAX ) { number_active_locals -= 251 - frame_type ; } else if ( frame_type == Const . FULL_FRAME ) { number_active_locals = stack_map_table [ i ] . getNumberOfLocals ( ) ; } // All other frame _ types do not modify locals .
} if ( stack_map_table . length == 0 ) { return - 1 ; } else { return stack_map_table . length - 1 ; }


signature:
public class StackMapUtils { /** * Find the index of the StackMap entry whose offset is the first one after the input argument .
 * Return - 1 if there isn ' t one . Also sets running _ offset .
 * @ param offset byte code offset
 * @ return the corresponding StackMapEntry index */
protected final @ IndexOrLow ( "stack_map_table" ) int find_stack_map_index_after ( int offset ) { } }

implementation:
running_offset = - 1 ; // no + 1 on first entry
for ( int i = 0 ; i < stack_map_table . length ; i ++ ) { running_offset = running_offset + stack_map_table [ i ] . getByteCodeOffset ( ) + 1 ; if ( running_offset > offset ) { return i ; } // try next map entry
} // no such entry found
return - 1 ;


signature:
public class StackMapUtils { /** * Check to see if ( due to some instruction modifications ) there have been any changes in a switch
 * statement ' s padding bytes . If so , then update the corresponding StackMap to reflect this
 * change .
 * @ param ih where to start looking for a switch instruction
 * @ param il instruction list to search */
protected final void modify_stack_maps_for_switches ( InstructionHandle ih , InstructionList il ) { } }

implementation:
Instruction inst ; short opcode ; if ( ! needStackMap ) { return ; } // Make sure all instruction offsets are uptodate .
il . setPositions ( ) ; // Loop through each instruction looking for a switch
while ( ih != null ) { inst = ih . getInstruction ( ) ; opcode = inst . getOpcode ( ) ; if ( opcode == Const . TABLESWITCH || opcode == Const . LOOKUPSWITCH ) { int current_offset = ih . getPosition ( ) ; int index = find_stack_map_index_after ( current_offset ) ; if ( index == - 1 ) { throw new RuntimeException ( "Invalid StackMap offset 3" ) ; } StackMapEntry stack_map = stack_map_table [ index ] ; int delta = ( current_offset + inst . getLength ( ) ) - running_offset ; if ( delta != 0 ) { stack_map . updateByteCodeOffset ( delta ) ; } // Since StackMap offsets are relative to the previous one
// we only have to do the first one after a switch .
// But we do need to look at all the switch instructions .
} // Go on to the next instruction in the list
ih = ih . getNext ( ) ; }


signature:
public class StackMapUtils { /** * Find the live range of the compiler temp ( s ) at the given offset and create a LocalVariableGen
 * for each . Note the compiler might generate temps of different sizes at the same offset ( must
 * have disjoint lifetimes ) .
 * @ param mgen the method
 * @ param offset compiler assigned local offset of hidden temp
 * @ return offset incremented by size of smallest temp found at offset */
protected final int gen_temp_locals ( MethodGen mgen , int offset ) { } }

implementation:
int live_start = 0 ; Type live_type = null ; InstructionList il = mgen . getInstructionList ( ) ; il . setPositions ( ) ; // Set up inital state of StackMap info on entry to method .
int locals_offset_height = 0 ; int byte_code_offset = - 1 ; LocalVariableGen new_lvg ; int min_size = 3 ; // only sizes are 1 or 2 ; start with something larger .
number_active_locals = initial_locals_count ; StackMapType [ ] types_of_active_locals = new StackMapType [ number_active_locals ] ; for ( int ii = 0 ; ii < number_active_locals ; ii ++ ) { types_of_active_locals [ ii ] = initial_type_list [ ii ] ; locals_offset_height += getSize ( initial_type_list [ ii ] ) ; } // update state for each StackMap entry
for ( StackMapEntry smte : stack_map_table ) { int frame_type = smte . getFrameType ( ) ; byte_code_offset += smte . getByteCodeOffset ( ) + 1 ; if ( frame_type >= Const . APPEND_FRAME && frame_type <= Const . APPEND_FRAME_MAX ) { // number to append is frame _ type - 251
types_of_active_locals = Arrays . copyOf ( types_of_active_locals , number_active_locals + frame_type - 251 ) ; for ( StackMapType smt : smte . getTypesOfLocals ( ) ) { types_of_active_locals [ number_active_locals ++ ] = smt ; locals_offset_height += getSize ( smt ) ; } } else if ( frame_type >= Const . CHOP_FRAME && frame_type <= Const . CHOP_FRAME_MAX ) { int number_to_chop = 251 - frame_type ; while ( number_to_chop > 0 ) { locals_offset_height -= getSize ( types_of_active_locals [ -- number_active_locals ] ) ; number_to_chop -- ; } types_of_active_locals = Arrays . copyOf ( types_of_active_locals , number_active_locals ) ; } else if ( frame_type == Const . FULL_FRAME ) { locals_offset_height = 0 ; number_active_locals = 0 ; types_of_active_locals = new StackMapType [ smte . getNumberOfLocals ( ) ] ; for ( StackMapType smt : smte . getTypesOfLocals ( ) ) { types_of_active_locals [ number_active_locals ++ ] = smt ; locals_offset_height += getSize ( smt ) ; } } // all other frame _ types do not modify locals .
// System . out . printf ( " byte _ code _ offset : % d , temp offset : % d , locals _ offset _ height : % d ,
// number _ active _ locals : % d , local types : % s % n " ,
// byte _ code _ offset , offset , locals _ offset _ height , number _ active _ locals ,
// Arrays . toString ( types _ of _ active _ locals ) ) ;
if ( live_start == 0 ) { // did the latest StackMap entry define the temp in question ?
if ( offset < locals_offset_height ) { live_start = byte_code_offset ; int running_offset = 0 ; for ( StackMapType smt : types_of_active_locals ) { if ( running_offset == offset ) { live_type = generate_Type_from_StackMapType ( smt ) ; break ; } running_offset += getSize ( smt ) ; } if ( live_type == null ) { // No matching offset in stack maps so this offset must be
// second half of long or double . Just skip to next stack map .
live_start = 0 ; } } } else { // did the latest StackMap entry undefine the temp in question ?
if ( offset >= locals_offset_height ) { // create the temp variable
new_lvg = mgen . addLocalVariable ( "DaIkOnTeMp" + offset , live_type , offset , il . findHandle ( live_start ) , il . findHandle ( byte_code_offset ) ) ; debug_instrument . log ( "Added local  %s, %d, %d : %s, %s%n" , new_lvg . getIndex ( ) , new_lvg . getStart ( ) . getPosition ( ) , new_lvg . getEnd ( ) . getPosition ( ) , new_lvg . getName ( ) , new_lvg . getType ( ) ) ; min_size = Math . min ( min_size , live_type . getSize ( ) ) ; // reset to look for more temps at same offset
live_start = 0 ; live_type = null ; } } // go on to next StackMap entry
} // we are done with stack maps ; need to see if any temps still active
if ( live_start != 0 ) { // live range is to end of method ; create the temp variable
new_lvg = mgen . addLocalVariable ( "DaIkOnTeMp" + offset , live_type , offset , il . findHandle ( live_start ) , null ) ; debug_instrument . log ( "Added local  %s, %d, %d : %s, %s%n" , new_lvg . getIndex ( ) , new_lvg . getStart ( ) . getPosition ( ) , il . getEnd ( ) . getPosition ( ) , new_lvg . getName ( ) , new_lvg . getType ( ) ) ; min_size = Math . min ( min_size , live_type . getSize ( ) ) ; } else { if ( min_size == 3 ) { // did not find a temp in any of the stack maps ; that must mean the
// temp live range is in between two stack maps or after last stack map
// need to scan all byte codes to get live range and type
// HACK : for now , just make a guess and put it after last stack map
// Note we may be defining a bogus temp for second half of long or double .
if ( byte_code_offset == - 1 ) { // no stack maps at all , set start to 0
byte_code_offset = 0 ; } new_lvg = mgen . addLocalVariable ( "DaIkOnTeMp" + offset , Type . OBJECT , offset , il . findHandle ( byte_code_offset ) , null ) ; debug_instrument . log ( "Added local  %s, %d, %d : %s, %s%n" , new_lvg . getIndex ( ) , new_lvg . getStart ( ) . getPosition ( ) , il . getEnd ( ) . getPosition ( ) , new_lvg . getName ( ) , new_lvg . getType ( ) ) ; min_size = Math . min ( min_size , Type . OBJECT . getSize ( ) ) ; } } return offset + min_size ;


signature:
public class StackMapUtils { /** * We need to locate and remember any NEW instructions that create uninitialized objects . Their
 * offset may be contained in a StackMap entry and will probably need to be updated as we add
 * instrumentation code . Note that these instructions are fairly rare .
 * @ param il instruction list to search */
protected final void build_unitialized_NEW_map ( InstructionList il ) { } }

implementation: uninitialized_NEW_map . clear ( ) ; il . setPositions ( ) ; for ( StackMapEntry smte : stack_map_table ) { int frame_type = smte . getFrameType ( ) ; if ( ( frame_type >= Const . SAME_LOCALS_1_STACK_ITEM_FRAME && frame_type <= Const . SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED ) || ( frame_type >= Const . APPEND_FRAME && frame_type <= Const . APPEND_FRAME_MAX ) || ( frame_type == Const . FULL_FRAME ) ) { if ( smte . getNumberOfLocals ( ) > 0 ) { for ( StackMapType smt : smte . getTypesOfLocals ( ) ) { if ( smt . getType ( ) == Const . ITEM_NewObject ) { int i = smt . getIndex ( ) ; uninitialized_NEW_map . put ( il . findHandle ( i ) , i ) ; } } } if ( smte . getNumberOfStackItems ( ) > 0 ) { for ( StackMapType smt : smte . getTypesOfStackItems ( ) ) { if ( smt . getType ( ) == Const . ITEM_NewObject ) { int i = smt . getIndex ( ) ; uninitialized_NEW_map . put ( il . findHandle ( i ) , i ) ; } } } } }


signature:
public class StackMapUtils { /** * One of uninitialized NEW instructions has moved . Update its offset in StackMap entries . Note
 * that more than one entry could refer to the same instruction . This is a helper routine used by
 * update _ uninitialized _ NEW _ offsets .
 * @ param old _ offset original location of NEW instruction
 * @ param new _ offset new location of NEW instruction */
private final void update_NEW_object_stack_map_entries ( int old_offset , int new_offset ) { } }

implementation: for ( StackMapEntry smte : stack_map_table ) { int frame_type = smte . getFrameType ( ) ; if ( ( frame_type >= Const . SAME_LOCALS_1_STACK_ITEM_FRAME && frame_type <= Const . SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED ) || ( frame_type >= Const . APPEND_FRAME && frame_type <= Const . APPEND_FRAME_MAX ) || ( frame_type == Const . FULL_FRAME ) ) { if ( smte . getNumberOfLocals ( ) > 0 ) { for ( StackMapType smt : smte . getTypesOfLocals ( ) ) { if ( smt . getType ( ) == Const . ITEM_NewObject ) { if ( old_offset == smt . getIndex ( ) ) { smt . setIndex ( new_offset ) ; } } } } if ( smte . getNumberOfStackItems ( ) > 0 ) { for ( StackMapType smt : smte . getTypesOfStackItems ( ) ) { if ( smt . getType ( ) == Const . ITEM_NewObject ) { if ( old_offset == smt . getIndex ( ) ) { smt . setIndex ( new_offset ) ; } } } } } }


signature:
public class StackMapUtils { /** * Check to see if any of the uninitialized NEW instructions have moved . Again , these are rare , so
 * a linear pass is fine .
 * @ param il instruction list to search */
protected final void update_uninitialized_NEW_offsets ( InstructionList il ) { } }

implementation: il . setPositions ( ) ; for ( Map . Entry < InstructionHandle , Integer > e : uninitialized_NEW_map . entrySet ( ) ) { InstructionHandle ih = e . getKey ( ) ; int old_offset = e . getValue ( ) . intValue ( ) ; int new_offset = ih . getPosition ( ) ; if ( old_offset != new_offset ) { update_NEW_object_stack_map_entries ( old_offset , new_offset ) ; e . setValue ( new_offset ) ; } }


signature:
public class StackMapUtils { /** * Process the instruction list , adding size ( 1 or 2 ) to the index of each Instruction that
 * references a local that is equal or higher in the local map than index _ first _ moved _ local . Size
 * should be the size of the new local that was just inserted at index _ first _ moved _ local .
 * @ param mgen MethodGen to be modified
 * @ param index _ first _ moved _ local original index of first local moved " up "
 * @ param size size of new local added ( 1 or 2) */
protected final void adjust_code_for_locals_change ( MethodGen mgen , int index_first_moved_local , int size ) { } }

implementation:
InstructionList il = mgen . getInstructionList ( ) ; for ( InstructionHandle ih = il . getStart ( ) ; ih != null ; ih = ih . getNext ( ) ) { Instruction inst = ih . getInstruction ( ) ; int orig_length = inst . getLength ( ) ; int operand ; if ( ( inst instanceof RET ) || ( inst instanceof IINC ) ) { IndexedInstruction index_inst = ( IndexedInstruction ) inst ; if ( index_inst . getIndex ( ) >= index_first_moved_local ) { index_inst . setIndex ( index_inst . getIndex ( ) + size ) ; } } else if ( inst instanceof LocalVariableInstruction ) { // BCEL handles all the details of which opcode and if index
// is implicit or explicit ; also , and if needs to be WIDE .
operand = ( ( LocalVariableInstruction ) inst ) . getIndex ( ) ; if ( operand >= index_first_moved_local ) { ( ( LocalVariableInstruction ) inst ) . setIndex ( operand + size ) ; } } // Unfortunately , BCEL doesn ' t take care of incrementing the
// offset within StackMapEntrys .
int delta = inst . getLength ( ) - orig_length ; if ( delta > 0 ) { il . setPositions ( ) ; update_stack_map_offset ( ih . getPosition ( ) , delta ) ; modify_stack_maps_for_switches ( ih , il ) ; } }


signature:
public class StackMapUtils { /** * Get existing StackMapTable from the MethodGen argument . If there is none , create a new empty
 * one . Sets both smta and stack _ map _ table . Must be called prior to any other methods that
 * manipulate the stack _ map _ table !
 * @ param mgen MethodGen to search
 * @ param java _ class _ version Java version for the classfile ; stack _ map _ table is optional before
 * Java 1.7 ( = classfile version 51) */
@ EnsuresNonNull ( { } }

implementation:
"stack_map_table" } ) protected final void set_current_stack_map_table ( MethodGen mgen , int java_class_version ) { smta = ( StackMap ) get_stack_map_table_attribute ( mgen ) ; if ( smta != null ) { // get a deep copy of the original StackMapTable .
stack_map_table = ( ( StackMap ) ( smta . copy ( smta . getConstantPool ( ) ) ) ) . getStackMap ( ) ; needStackMap = true ; debug_instrument . log ( "Attribute tag: %s length: %d nameIndex: %d%n" , smta . getTag ( ) , smta . getLength ( ) , smta . getNameIndex ( ) ) ; // Delete existing stack map - we ' ll add a new one later .
mgen . removeCodeAttribute ( smta ) ; } else { stack_map_table = empty_stack_map_table ; if ( java_class_version > Const . MAJOR_1_6 ) { needStackMap = true ; } } print_stack_map_table ( "Original" ) ;


signature:
public class StackMapUtils { /** * Print the contents of the StackMapTable to the debug _ instrument . log .
 * @ param prefix label to display with table */
protected final void print_stack_map_table ( String prefix ) { } }

implementation:
debug_instrument . log ( "%nStackMap(%s) %s items:%n" , prefix , stack_map_table . length ) ; running_offset = - 1 ; // no + 1 on first entry
for ( int i = 0 ; i < stack_map_table . length ; i ++ ) { running_offset = stack_map_table [ i ] . getByteCodeOffset ( ) + running_offset + 1 ; debug_instrument . log ( "@%03d %s %n" , running_offset , stack_map_table [ i ] ) ; }


signature:
public class StackMapUtils { /** * Create a new StackMap code attribute from stack _ map _ table .
 * @ param mgen MethodGen to add attribute to
 * @ throws IOException if cannot create the attribute */
protected final void create_new_stack_map_attribute ( MethodGen mgen ) throws IOException { } }

implementation:
if ( ! needStackMap ) { return ; } if ( stack_map_table == empty_stack_map_table ) { return ; } print_stack_map_table ( "Final" ) ; // Build new StackMapTable attribute
StackMap map_table = new StackMap ( pool . addUtf8 ( "StackMapTable" ) , 0 , null , pool . getConstantPool ( ) ) ; map_table . setStackMap ( stack_map_table ) ; mgen . addCodeAttribute ( map_table ) ;


signature:
public class StackMapUtils { /** * Convert a Type name to a Class name .
 * @ param t type whose name is to be converted
 * @ return a String containing the class name */
@ SuppressWarnings ( "signature" ) // conversion routine
protected static @ ClassGetName String typeToClassGetName ( Type t ) { } }

implementation:
if ( t instanceof ObjectType ) { return ( ( ObjectType ) t ) . getClassName ( ) ; } else if ( t instanceof BasicType ) { // Use reserved keyword for basic type rather than signature to
// avoid conflicts with user defined types .
return t . toString ( ) ; } else { // Array type : just convert ' / ' to ' . '
return t . getSignature ( ) . replace ( '/' , '.' ) ; }


signature:
public class StackMapUtils { /** * Convert a Type to a StackMapType .
 * @ param t Type to be converted
 * @ return result StackMapType */
protected final StackMapType generate_StackMapType_from_Type ( Type t ) { } }

implementation:
switch ( t . getType ( ) ) { case Const . T_BOOLEAN : case Const . T_CHAR : case Const . T_BYTE : case Const . T_SHORT : case Const . T_INT : return new StackMapType ( Const . ITEM_Integer , - 1 , pool . getConstantPool ( ) ) ; case Const . T_FLOAT : return new StackMapType ( Const . ITEM_Float , - 1 , pool . getConstantPool ( ) ) ; case Const . T_DOUBLE : return new StackMapType ( Const . ITEM_Double , - 1 , pool . getConstantPool ( ) ) ; case Const . T_LONG : return new StackMapType ( Const . ITEM_Long , - 1 , pool . getConstantPool ( ) ) ; case Const . T_ARRAY : case Const . T_OBJECT : return new StackMapType ( Const . ITEM_Object , pool . addClass ( typeToClassGetName ( t ) ) , pool . getConstantPool ( ) ) ; // UNKNOWN seems to be used for Uninitialized objects .
// The second argument to the constructor should be the code offset
// of the corresponding ' new ' instruction . Just using 0 for now .
case Const . T_UNKNOWN : return new StackMapType ( Const . ITEM_NewObject , 0 , pool . getConstantPool ( ) ) ; default : throw new RuntimeException ( "Invalid type: " + t + t . getType ( ) ) ; }


signature:
public class StackMapUtils { /** * Convert a StackMapType to a Type .
 * @ param smt StackMapType to be converted
 * @ return result Type */
protected final Type generate_Type_from_StackMapType ( StackMapType smt ) { } }

implementation:
switch ( smt . getType ( ) ) { case Const . ITEM_Integer : case Const . ITEM_Bogus : // not sure about this ; reresents ' top ' ?
return Type . INT ; case Const . ITEM_Float : return Type . FLOAT ; case Const . ITEM_Double : return Type . DOUBLE ; case Const . ITEM_Long : return Type . LONG ; case Const . ITEM_Object : return Type . OBJECT ; default : Thread . dumpStack ( ) ; assert false : "Invalid StackMapType: " + smt + smt . getType ( ) ; throw new RuntimeException ( "Invalid StackMapType: " + smt + smt . getType ( ) ) ; }


signature:
public class StackMapUtils { /** * Update any FULL _ FRAME StackMap entries to include a new local var . The locals array is a copy
 * of the local variables PRIOR to the addition of the new local in question .
 * @ param offset offset into stack of the new variable we are adding
 * @ param type _ new _ var type of new variable we are adding
 * @ param locals a copy of the local variable table prior to this modification */
protected final void update_full_frame_stack_map_entries ( int offset , Type type_new_var , LocalVariableGen [ ] locals ) { } }

implementation:
@ NonNegative int index ; // locals index
for ( int i = 0 ; i < stack_map_table . length ; i ++ ) { if ( stack_map_table [ i ] . getFrameType ( ) == Const . FULL_FRAME ) { int num_locals = stack_map_table [ i ] . getNumberOfLocals ( ) ; StackMapType [ ] new_local_types = new StackMapType [ num_locals + 1 ] ; StackMapType [ ] old_local_types = stack_map_table [ i ] . getTypesOfLocals ( ) ; // System . out . printf ( " update _ full _ frame % s % s % s % n " , offset , num _ locals , locals . length ) ;
for ( index = 0 ; index < num_locals ; index ++ ) { if ( index >= locals . length ) { // there are hidden compiler temps in map
break ; } if ( locals [ index ] . getIndex ( ) >= offset ) { // we ' ve reached the point of insertion
break ; } new_local_types [ index ] = old_local_types [ index ] ; } new_local_types [ index ++ ] = generate_StackMapType_from_Type ( type_new_var ) ; while ( index <= num_locals ) { new_local_types [ index ] = old_local_types [ index - 1 ] ; index ++ ; } stack_map_table [ i ] . setTypesOfLocals ( new_local_types ) ; } }


signature:
public class StackMapUtils { /** * Add a new parameter to the method . This will be added after last current parameter and before
 * the first local variable . This might have the side effect of causing us to rewrite the method
 * byte codes to adjust the offsets for the local variables - see below for details .
 * < p > Must call fix _ local _ variable _ table ( just once per method ) before calling this routine .
 * @ param mgen MethodGen to be modified
 * @ param arg _ name name of new parameter
 * @ param arg _ type type of new parameter
 * @ return a LocalVariableGen for the new parameter
 * @ deprecated use { @ link # add _ new _ parameter } */
@ Deprecated // use add _ new _ parameter ( )
protected final LocalVariableGen add_new_argument ( MethodGen mgen , String arg_name , Type arg_type ) { } }

implementation: return add_new_parameter ( mgen , arg_name , arg_type ) ;


signature:
public class StackMapUtils { /** * Add a new parameter to the method . This will be added after last current parameter and before
 * the first local variable . This might have the side effect of causing us to rewrite the method
 * byte codes to adjust the offsets for the local variables - see below for details .
 * < p > Must call fix _ local _ variable _ table ( just once per method ) before calling this routine .
 * @ param mgen MethodGen to be modified
 * @ param arg _ name name of new parameter
 * @ param arg _ type type of new parameter
 * @ return a LocalVariableGen for the new parameter */
protected final LocalVariableGen add_new_parameter ( MethodGen mgen , String arg_name , Type arg_type ) { } }

implementation:
// We add a new parameter , after any current ones , and then
// we need to make a pass over the byte codes to update the local
// offset values of all the locals we just shifted up . This may have
// a ' knock on ' effect if we are forced to change an instruction that
// references implict local # 3 to an instruction with an explict
// reference to local # 4 as this would require the insertion of an
// offset into the byte codes . This means we would need to make an
// additional pass to update branch targets ( no - BCEL does this for
// us ) and the StackMapTable ( yes - BCEL should do this , but it doesn ' t ) .
LocalVariableGen arg_new = null ; // get a copy of the locals before modification
LocalVariableGen [ ] locals = mgen . getLocalVariables ( ) ; Type [ ] arg_types = mgen . getArgumentTypes ( ) ; int new_index = 0 ; int new_offset = 0 ; boolean has_code = ( mgen . getInstructionList ( ) != null ) ; if ( has_code ) { if ( ! mgen . isStatic ( ) ) { // Skip the ' this ' pointer .
new_index ++ ; new_offset ++ ; // size of ' this ' is 1
} if ( arg_types . length > 0 ) { LocalVariableGen last_arg ; new_index = new_index + arg_types . length ; // new _ index is now positive , because arg _ types . length is
last_arg = locals [ new_index - 1 ] ; new_offset = last_arg . getIndex ( ) + ( last_arg . getType ( ) ) . getSize ( ) ; } // Insert our new local variable into existing table at ' new _ offset ' .
arg_new = mgen . addLocalVariable ( arg_name , arg_type , new_offset , null , null ) ; // Update the index of the first ' true ' local in the local variable table .
first_local_index ++ ; } initial_locals_count ++ ; // Update the method ' s parameter information .
arg_types = BcelUtil . postpendToArray ( arg_types , arg_type ) ; String [ ] arg_names = add_string ( mgen . getArgumentNames ( ) , arg_name ) ; mgen . setArgumentTypes ( arg_types ) ; mgen . setArgumentNames ( arg_names ) ; if ( has_code ) { // we need to adjust the offset of any locals after our insertion
for ( int i = new_index ; i < locals . length ; i ++ ) { LocalVariableGen lv = locals [ i ] ; lv . setIndex ( lv . getIndex ( ) + arg_type . getSize ( ) ) ; } mgen . setMaxLocals ( mgen . getMaxLocals ( ) + arg_type . getSize ( ) ) ; debug_instrument . log ( "Added arg    %s%n" , arg_new . getIndex ( ) + ": " + arg_new . getName ( ) + ", " + arg_new . getType ( ) ) ; // Now process the instruction list , adding one to the offset
// within each LocalVariableInstruction that references a
// local that is ' higher ' in the local map than new local
// we just inserted .
adjust_code_for_locals_change ( mgen , new_offset , arg_type . getSize ( ) ) ; // Finally , we need to update any FULL _ FRAME StackMap entries to
// add in the new local variable type .
update_full_frame_stack_map_entries ( new_offset , arg_type , locals ) ; debug_instrument . log ( "New LocalVariableTable:%n%s%n" , mgen . getLocalVariableTable ( pool ) ) ; } return arg_new ;


signature:
public class StackMapUtils { /** * Create a new local with a scope of the full method . This means we need to search the existing
 * locals to find the proper index for our new local . This might have the side effect of causing
 * us to rewrite the method byte codes to adjust the offsets for the existing local variables -
 * see below for details .
 * < p > Must call fix _ local _ variable _ table ( just once per method ) before calling this routine .
 * @ param mgen MethodGen to be modified
 * @ param local _ name name of new local
 * @ param local _ type type of new local
 * @ return a LocalVariableGen for the new local */
protected final LocalVariableGen create_method_scope_local ( MethodGen mgen , String local_name , Type local_type ) { } }

implementation:
// BCEL sorts local vars and presents them in offset order . Search
// locals for first var with start ! = 0 . If none , just add the new
// var at the end of the table and exit . Otherwise , insert the new
// var just prior to the local we just found .
// Now we need to make a pass over the byte codes to update the local
// offset values of all the locals we just shifted up . This may have
// a ' knock on ' effect if we are forced to change an instruction that
// references implict local # 3 to an instruction with an explict
// reference to local # 4 as this would require the insertion of an
// offset into the byte codes . This means we would need to make an
// additional pass to update branch targets ( no - BCEL does this for
// us ) and the StackMapTable ( yes - BCEL should do this , but it doesn ' t ) .
// We never want to insert our local prior to any parameters . This would
// happen naturally , but some old class files have non zero addresses
// for ' this ' and / or the parameters so we need to add an explicit
// check to make sure we skip these variables .
LocalVariableGen lv_new ; int max_offset = 0 ; int new_offset = - 1 ; // get a copy of the local before modification
LocalVariableGen [ ] locals = mgen . getLocalVariables ( ) ; @ IndexOrLow ( "locals" ) int compiler_temp_i = - 1 ; int new_index = - 1 ; int i ; for ( i = 0 ; i < locals . length ; i ++ ) { LocalVariableGen lv = locals [ i ] ; if ( i >= first_local_index ) { if ( lv . getStart ( ) . getPosition ( ) != 0 ) { if ( new_offset == - 1 ) { if ( compiler_temp_i != - 1 ) { new_offset = locals [ compiler_temp_i ] . getIndex ( ) ; new_index = compiler_temp_i ; } else { new_offset = lv . getIndex ( ) ; new_index = i ; } } } } // calculate max local size seen so far ( + 1)
max_offset = lv . getIndex ( ) + lv . getType ( ) . getSize ( ) ; if ( lv . getName ( ) . startsWith ( "DaIkOnTeMp" ) ) { // Remember the index of a compiler temp . We may wish
// to insert our new local prior to a temp to simplfy
// the generation of StackMaps .
if ( compiler_temp_i == - 1 ) { compiler_temp_i = i ; } } else { // If there were compiler temps prior to this local , we don ' t
// need to worry about them as the compiler will have already
// included them in the StackMaps . Reset the indicators .
compiler_temp_i = - 1 ; } } // We have looked at all the local variables ; if we have not found
// a place for our new local , check to see if last local was a
// compiler temp and insert prior .
if ( ( new_offset == - 1 ) && ( compiler_temp_i != - 1 ) ) { new_offset = locals [ compiler_temp_i ] . getIndex ( ) ; new_index = compiler_temp_i ; } // If new _ offset is still unset , we can just add our local at the
// end . There may be unnamed compiler temps here , so we need to
// check for this ( via max _ offset ) and move them up .
if ( new_offset == - 1 ) { new_offset = max_offset ; if ( new_offset < mgen . getMaxLocals ( ) ) { mgen . setMaxLocals ( mgen . getMaxLocals ( ) + local_type . getSize ( ) ) ; } lv_new = mgen . addLocalVariable ( local_name , local_type , new_offset , null , null ) ; } else { // insert our new local variable into existing table at ' new _ offset '
lv_new = mgen . addLocalVariable ( local_name , local_type , new_offset , null , null ) ; // we need to adjust the offset of any locals after our insertion
for ( i = new_index ; i < locals . length ; i ++ ) { LocalVariableGen lv = locals [ i ] ; lv . setIndex ( lv . getIndex ( ) + local_type . getSize ( ) ) ; } mgen . setMaxLocals ( mgen . getMaxLocals ( ) + local_type . getSize ( ) ) ; } debug_instrument . log ( "Added local  %s%n" , lv_new . getIndex ( ) + ": " + lv_new . getName ( ) + ", " + lv_new . getType ( ) ) ; // Now process the instruction list , adding one to the offset
// within each LocalVariableInstruction that references a
// local that is ' higher ' in the local map than new local
// we just inserted .
adjust_code_for_locals_change ( mgen , new_offset , local_type . getSize ( ) ) ; // Finally , we need to update any FULL _ FRAME StackMap entries to
// add in the new local variable type .
update_full_frame_stack_map_entries ( new_offset , local_type , locals ) ; debug_instrument . log ( "New LocalVariableTable:%n%s%n" , mgen . getLocalVariableTable ( pool ) ) ; return lv_new ;


signature:
public class StackMapUtils { /** * Under some circumstances , there may be problems with the local variable table . These problems
 * occur when the Java compiler adds unnamed entries . There may be unnamed parameters and / or
 * unnamed local variables . These items appear as gaps in the LocalVariable table . This routine
 * creates LocalVariable entries for these missing items .
 * < ol >
 * < li > The java Compiler allocates a hidden parameter for the constructor of an inner class .
 * These items are given the name $ hidden $ appended with their offset .
 * < li > The Java compiler allocates unnamed local temps for :
 * < ul >
 * < li > saving the exception in a finally clause
 * < li > the lock for a synchronized block
 * < li > interators
 * < li > ( others ? )
 * < / ul >
 * These items are given the name DaIkOnTeMp appended with their offset .
 * < / ol >
 * @ param mgen MethodGen to be modified */
protected final void fix_local_variable_table ( MethodGen mgen ) { } }

implementation:
InstructionList il = mgen . getInstructionList ( ) ; if ( il == null ) { // no code so nothing to do
first_local_index = 0 ; return ; } // Get the current local variables ( includes ' this ' and parameters )
LocalVariableGen [ ] locals = mgen . getLocalVariables ( ) ; LocalVariableGen l ; LocalVariableGen new_lvg ; // We need a deep copy
for ( int ii = 0 ; ii < locals . length ; ii ++ ) { locals [ ii ] = ( LocalVariableGen ) ( locals [ ii ] . clone ( ) ) ; } // The arg types are correct and include all parameters .
Type [ ] arg_types = mgen . getArgumentTypes ( ) ; // Initial offset into the stack frame
int offset = 0 ; // Index into locals of the first parameter
int loc_index = 0 ; // Rarely , the java compiler gets the max locals count wrong ( too big ) .
// This would cause problems for us later , so we need to recalculate
// the highest local used based on looking at code offsets .
mgen . setMaxLocals ( ) ; int max_locals = mgen . getMaxLocals ( ) ; // Remove the existing locals
mgen . removeLocalVariables ( ) ; // Reset MaxLocals to 0 and let code below rebuild it .
mgen . setMaxLocals ( 0 ) ; // Determine the first ' true ' local index into the local variables .
// The object ' this ' pointer and the parameters form the first n
// entries in the list .
first_local_index = arg_types . length ; if ( ! mgen . isStatic ( ) ) { // Add the ' this ' pointer back in .
l = locals [ 0 ] ; new_lvg = mgen . addLocalVariable ( l . getName ( ) , l . getType ( ) , l . getIndex ( ) , null , null ) ; debug_instrument . log ( "Added <this> %s%n" , new_lvg . getIndex ( ) + ": " + new_lvg . getName ( ) + ", " + new_lvg . getType ( ) ) ; loc_index = 1 ; offset = 1 ; first_local_index ++ ; } // Loop through each parameter
for ( int ii = 0 ; ii < arg_types . length ; ii ++ ) { // If this parameter doesn ' t have a matching local
if ( ( loc_index >= locals . length ) || ( offset != locals [ loc_index ] . getIndex ( ) ) ) { // Create a local variable to describe the missing parameter
new_lvg = mgen . addLocalVariable ( "$hidden$" + offset , arg_types [ ii ] , offset , null , null ) ; } else { l = locals [ loc_index ] ; new_lvg = mgen . addLocalVariable ( l . getName ( ) , l . getType ( ) , l . getIndex ( ) , null , null ) ; loc_index ++ ; } debug_instrument . log ( "Added param  %s%n" , new_lvg . getIndex ( ) + ": " + new_lvg . getName ( ) + ", " + new_lvg . getType ( ) ) ; offset += arg_types [ ii ] . getSize ( ) ; } // At this point the LocalVaraibles contain :
// the ' this ' pointer ( if present )
// the parameters to the method
// This will be used to construct the initial state of the
// StackMapTypes .
LocalVariableGen [ ] initial_locals = mgen . getLocalVariables ( ) ; initial_locals_count = initial_locals . length ; initial_type_list = new StackMapType [ initial_locals_count ] ; for ( int ii = 0 ; ii < initial_locals_count ; ii ++ ) { initial_type_list [ ii ] = generate_StackMapType_from_Type ( initial_locals [ ii ] . getType ( ) ) ; } // Add back the true locals
// NOTE that the Java compiler uses unnamed local temps for :
// saving the exception in a finally clause
// the lock for a synchronized block
// iterators
// ( others ? )
// We will create a ' fake ' local for these cases .
for ( int ii = first_local_index ; ii < locals . length ; ii ++ ) { l = locals [ ii ] ; if ( l . getIndex ( ) > offset ) { // A gap in index values indicates a compiler allocated temp .
// ( if offset is 0 , probably a lock object )
// there is at least one hidden compiler temp before the next local
offset = gen_temp_locals ( mgen , offset ) ; ii -- ; // need to revisit same local
} else { new_lvg = mgen . addLocalVariable ( l . getName ( ) , l . getType ( ) , l . getIndex ( ) , l . getStart ( ) , l . getEnd ( ) ) ; debug_instrument . log ( "Added local  %s%n" , new_lvg . getIndex ( ) + ": " + new_lvg . getName ( ) + ", " + new_lvg . getType ( ) ) ; offset = new_lvg . getIndex ( ) + ( new_lvg . getType ( ) ) . getSize ( ) ; } } // check for hidden temps after last declared local .
while ( offset < max_locals ) { offset = gen_temp_locals ( mgen , offset ) ; } // Recalculate the highest local used based on looking at code offsets .
mgen . setMaxLocals ( ) ;


signature:
public class StackMapUtils { /** * Calculates the types on the stack for each instruction using the BCEL stack verification
 * routines .
 * @ param mg MethodGen for the method to be analyzed
 * @ return a StackTypes object for the method */
protected final StackTypes bcel_calc_stack_types ( MethodGen mg ) { } }

implementation: StackVer stackver = new StackVer ( ) ; VerificationResult vr ; try { vr = stackver . do_stack_ver ( mg ) ; } catch ( Throwable t ) { System . out . printf ( "Warning: StackVer exception for %s.%s%n" , mg . getClassName ( ) , mg . getName ( ) ) ; System . out . printf ( "Exception: %s%n" , t ) ; System . out . printf ( "Method is NOT instrumented%n" ) ; return null ; } if ( vr != VerificationResult . VR_OK ) { System . out . printf ( "Warning: StackVer failed for %s.%s: %s%n" , mg . getClassName ( ) , mg . getName ( ) , vr ) ; System . out . printf ( "Method is NOT instrumented%n" ) ; return null ; } assert vr == VerificationResult . VR_OK : " vr failed " + vr ; return stackver . get_stack_types ( ) ;


signature:
public class BcelUtil { /** * Returns a string describing a method declaration . It contains the access flags ( public ,
 * private , static , etc ) , the return type , the method name , and the types of each of its
 * parameters .
 * < p > For example , if the orignal Java source declarationwas : private final String
 * constantToString ( int index ) Then the output of methodDeclarationToString would be : private
 * final java . lang . String constantToString ( int )
 * @ param m the method
 * @ return a string describing the method declaration */
public static String methodDeclarationToString ( Method m ) { } }

implementation:
StringBuilder sb = new StringBuilder ( ) ; String flags = accessFlagsToString ( m ) ; boolean argsExist = false ; if ( flags != null && ! flags . isEmpty ( ) ) { sb . append ( String . format ( "%s " , flags ) ) ; } sb . append ( String . format ( "%s %s(" , m . getReturnType ( ) , m . getName ( ) ) ) ; for ( Type at : m . getArgumentTypes ( ) ) { sb . append ( String . format ( "%s, " , at ) ) ; argsExist = true ; } if ( argsExist ) { sb . setLength ( sb . length ( ) - 2 ) ; // remove trailing " , "
} sb . append ( ")" ) ; return sb . toString ( ) ;


signature:
public class BcelUtil { /** * Return a string representation of the access flags of method m . In the string , the flags are
 * space - separated and in a canonical order .
 * @ param m the method whose access flags to retrieve
 * @ return a string representation of the access flags of method m */
static String accessFlagsToString ( Method m ) { } }

implementation:
int flags = m . getAccessFlags ( ) ; StringBuilder buf = new StringBuilder ( ) ; // Note that pow is a binary mask for the flag ( = 2 ^ i ) .
for ( int i = 0 , pow = 1 ; i <= Const . MAX_ACC_FLAG ; i ++ ) { if ( ( flags & pow ) != 0 ) { if ( buf . length ( ) > 0 ) { buf . append ( " " ) ; } if ( i < Const . ACCESS_NAMES_LENGTH ) { buf . append ( Const . getAccessName ( i ) ) ; } else { buf . append ( String . format ( "ACC_BIT(%x)" , pow ) ) ; } } pow <<= 1 ; } return buf . toString ( ) ;


signature:
public class BcelUtil { /** * Return a printed description of the given instructions .
 * @ param il the instructions to describe
 * @ param pool the constant pool the instructions refer to
 * @ return a printed representation of the instructions in { @ code il } */
public static String instructionListToString ( InstructionList il , ConstantPoolGen pool ) { } }

implementation: StringBuilder out = new StringBuilder ( ) ; for ( Iterator < InstructionHandle > i = il . iterator ( ) ; i . hasNext ( ) ; ) { InstructionHandle handle = i . next ( ) ; out . append ( handle . getInstruction ( ) . toString ( pool . getConstantPool ( ) ) + "\n" ) ; } return out . toString ( ) ;


signature:
public class BcelUtil { /** * Return a description of the local variables ( one per line ) .
 * @ param mg the method whose local variables to describe
 * @ return a description of the local variables ( one per line ) */
public static String localVariablesToString ( MethodGen mg ) { } }

implementation: StringBuilder out = new StringBuilder ( ) ; out . append ( String . format ( "Locals for %s [cnt %d]%n" , mg , mg . getMaxLocals ( ) ) ) ; LocalVariableGen [ ] lvgs = mg . getLocalVariables ( ) ; if ( ( lvgs != null ) && ( lvgs . length > 0 ) ) { for ( LocalVariableGen lvg : lvgs ) { out . append ( String . format ( "  %s [index %d]%n" , lvg , lvg . getIndex ( ) ) ) ; } } return out . toString ( ) ;


signature:
public class BcelUtil { /** * Return the attribute name for the specified attribute , looked up in the original class file
 * ConstantPool .
 * @ param a the attribute
 * @ return the attribute name for the specified attribute */
public static String attributeNameToString ( Attribute a ) { } }

implementation: ConstantPool pool = a . getConstantPool ( ) ; int conIndex = a . getNameIndex ( ) ; Constant c = pool . getConstant ( conIndex ) ; String attName = ( ( ConstantUtf8 ) c ) . getBytes ( ) ; return attName ;


signature:
public class BcelUtil { /** * Returns whether or not the method is a constructor .
 * @ param mg the MethodGen to test
 * @ return true iff the method is a constructor */
public static boolean isConstructor ( MethodGen mg ) { } }

implementation: if ( mg . getName ( ) . equals ( "" ) ) { throw new Error ( "method name cannot be empty" ) ; } return mg . getName ( ) . equals ( "<init>" ) ;


signature:
public class BcelUtil { /** * Returns whether or not the method is a constructor .
 * @ param m the Method to test
 * @ return true iff the method is a constructor */
public static boolean isConstructor ( Method m ) { } }

implementation: if ( m . getName ( ) . equals ( "" ) ) { throw new Error ( "method name cannot be empty" ) ; } return m . getName ( ) . equals ( "<init>" ) ;


signature:
public class BcelUtil { /** * Returns whether or not the class is part of the JDK ( rt . jar ) .
 * @ param classname the class to test , in the format of Class . getName ( ) ; the class should not be
 * an array
 * @ return true iff the class is in a package that is in the JDK ( rt . jar ) */
public static boolean inJdk ( @ ClassGetName String classname ) { } }

implementation: return classname . startsWith ( "java." ) || classname . startsWith ( "com.oracle." ) || classname . startsWith ( "com.sun." ) || classname . startsWith ( "javax." ) || classname . startsWith ( "jdk." ) || classname . startsWith ( "org.ietf." ) || classname . startsWith ( "org.jcp." ) || classname . startsWith ( "org.omg." ) || classname . startsWith ( "org.w3c." ) || classname . startsWith ( "org.xml." ) || classname . startsWith ( "sun." ) || classname . startsWith ( "sunw." ) ;


signature:
public class BcelUtil { /** * Returns whether or not the class is part of the JDK ( rt . jar ) .
 * @ param classname the class to test , in internal form
 * @ return true iff the class is part of the JDK ( rt . jar ) */
public static boolean inJdkInternalform ( @ InternalForm String classname ) { } }

implementation: return classname . startsWith ( "java/" ) || classname . startsWith ( "com/oracle/" ) || classname . startsWith ( "com/sun/" ) || classname . startsWith ( "javax/" ) || classname . startsWith ( "jdk/" ) || classname . startsWith ( "org/ietj/" ) || classname . startsWith ( "org/jcp/" ) || classname . startsWith ( "org/omg/" ) || classname . startsWith ( "org/w3c/" ) || classname . startsWith ( "org/xml/" ) || classname . startsWith ( "sun/" ) || classname . startsWith ( "sunw/" ) ;


signature:
public class BcelUtil { /** * Returns whether or not this is a standard main method ( static , void , name is ' main ' , and one
 * formal parameter : a string array ) .
 * @ param mg the method to check
 * @ return true iff the method is a main method */
public static boolean isMain ( MethodGen mg ) { } }

implementation: Type [ ] argTypes = mg . getArgumentTypes ( ) ; return mg . isStatic ( ) && ( mg . getReturnType ( ) == Type . VOID ) && mg . getName ( ) . equals ( "main" ) && ( argTypes . length == 1 ) && argTypes [ 0 ] . equals ( stringArray ) ;


signature:
public class BcelUtil { /** * Checks the specified method for consistency .
 * < p > Does nothing if { @ link # skipChecks } is false .
 * @ param mgen the class to check */
public static void checkMgen ( MethodGen mgen ) { } }

implementation:
if ( skipChecks ) { return ; } try { mgen . toString ( ) ; // ensure it can be formatted without exceptions
mgen . getLineNumberTable ( mgen . getConstantPool ( ) ) ; InstructionList ilist = mgen . getInstructionList ( ) ; if ( ilist == null || ilist . getStart ( ) == null ) { return ; } CodeExceptionGen [ ] exceptionHandlers = mgen . getExceptionHandlers ( ) ; for ( CodeExceptionGen gen : exceptionHandlers ) { assert ilist . contains ( gen . getStartPC ( ) ) : "exception handler " + gen + " has been forgotten in " + mgen . getClassName ( ) + "." + mgen . getName ( ) ; } MethodGen nmg = new MethodGen ( mgen . getMethod ( ) , mgen . getClassName ( ) , mgen . getConstantPool ( ) ) ; nmg . getLineNumberTable ( mgen . getConstantPool ( ) ) ; } catch ( Throwable t ) { Error e = new Error ( String . format ( "failure while checking method %s.%s%n" , mgen . getClassName ( ) , mgen . getName ( ) ) , t ) ; e . printStackTrace ( ) ; throw e ; }


signature:
public class BcelUtil { /** * Checks all of the methods in gen for consistency .
 * @ param gen the class to check */
public static void checkMgens ( final ClassGen gen ) { } }

implementation:
if ( skipChecks ) { return ; } Method [ ] methods = gen . getMethods ( ) ; for ( int i = 0 ; i < methods . length ; i ++ ) { Method method = methods [ i ] ; // System . out . println ( " Checking method " + method + " in class "
// + gen . getClassName ( ) ) ;
checkMgen ( new MethodGen ( method , gen . getClassName ( ) , gen . getConstantPool ( ) ) ) ; } // Diagnostic output
if ( false ) { dumpStackTrace ( ) ; dumpMethods ( gen ) ; }


signature:
public class BcelUtil { /** * Print the current java call stack . */
public static void dumpStackTrace ( ) { } }

implementation:
StackTraceElement [ ] ste = Thread . currentThread ( ) . getStackTrace ( ) ; // [0 ] is getStackTrace
// [1 ] is dumpStackTrace
if ( ste . length < 3 ) { System . out . println ( "No stack trace information available" ) ; } else { StackTraceElement caller = ste [ 2 ] ; System . out . printf ( "%s.%s (%s line %d)" , caller . getClassName ( ) , caller . getMethodName ( ) , caller . getFileName ( ) , caller . getLineNumber ( ) ) ; for ( int ii = 3 ; ii < ste . length ; ii ++ ) { System . out . printf ( " [%s line %d]" , ste [ ii ] . getFileName ( ) , ste [ ii ] . getLineNumber ( ) ) ; } System . out . printf ( "%n" ) ; }


signature:
public class BcelUtil { /** * Print the methods in the class , to standard output .
 * @ param gen the class whose methods to print */
static void dumpMethods ( ClassGen gen ) { } }

implementation: System . out . printf ( "Class %s methods:%n" , gen . getClassName ( ) ) ; for ( Method m : gen . getMethods ( ) ) { System . out . printf ( "  %s%n" , m ) ; }


signature:
public class BcelUtil { /** * Dumps the contents of the specified class to the specified directory . The file is named
 * dumpDir / [ class ] . bcel . It contains a synopsis of the fields and methods followed by the JVM code
 * for each method .
 * @ param jc JavaClass to dump
 * @ param dumpDir directory in which to write the file */
public static void dump ( JavaClass jc , File dumpDir ) { } }

implementation:
try { dumpDir . mkdir ( ) ; File path = new File ( dumpDir , jc . getClassName ( ) + ".bcel" ) ; PrintStream p = new PrintStream ( path ) ; // Print the class , superclass , and interfaces
p . printf ( "class %s extends %s%n" , jc . getClassName ( ) , jc . getSuperclassName ( ) ) ; String [ ] inames = jc . getInterfaceNames ( ) ; boolean first = true ; if ( ( inames != null ) && ( inames . length > 0 ) ) { p . printf ( "   implements " ) ; for ( String iname : inames ) { if ( ! first ) p . printf ( ", " ) ; p . printf ( "%s" , iname ) ; first = false ; } p . printf ( "%n" ) ; } // Print each field
p . printf ( "%nFields%n" ) ; for ( Field f : jc . getFields ( ) ) { p . printf ( "  %s%n" , f ) ; } // Print the signature of each method
p . printf ( "%nMethods%n" ) ; for ( Method m : jc . getMethods ( ) ) { p . printf ( "  %s%n" , m ) ; } for ( Method m : jc . getMethods ( ) ) { Code code = m . getCode ( ) ; if ( code != null ) { p . printf ( "%nMethod %s%n" , m ) ; p . printf ( "  %s%n" , code . toString ( ) . replace ( "\n" , "\n  " ) ) ; } } // Print the details of the constant pool .
p . printf ( "Constant Pool:%n" ) ; ConstantPool cp = jc . getConstantPool ( ) ; Constant [ ] constants = cp . getConstantPool ( ) ; for ( int ii = 0 ; ii < constants . length ; ii ++ ) { p . printf ( "  %d %s%n" , ii , constants [ ii ] ) ; } p . close ( ) ; } catch ( Exception e ) { throw new Error ( "Unexpected error dumping JavaClass: " + jc . getClassName ( ) + " to " + dumpDir . getName ( ) , e ) ; }


signature:
public class BcelUtil { /** * Adds instructions to the start of a method .
 * @ param mg method to be augmented
 * @ param newList instructions to prepend to the method */
public static void addToStart ( MethodGen mg , InstructionList newList ) { } }

implementation:
// Add the code before the first instruction
InstructionList il = mg . getInstructionList ( ) ; InstructionHandle oldStart = il . getStart ( ) ; InstructionHandle newStart = il . insert ( newList ) ; // Move any LineNumbers and local variables that currently point to
// the first instruction to include the new instructions . Other
// targeters ( branches , exceptions ) should not include the new code .
if ( oldStart . hasTargeters ( ) ) { // getTargeters ( ) returns non - null because hasTargeters = > true
for ( InstructionTargeter it : oldStart . getTargeters ( ) ) { if ( ( it instanceof LineNumberGen ) || ( it instanceof LocalVariableGen ) ) { it . updateTarget ( oldStart , newStart ) ; } } } mg . setMaxStack ( ) ; mg . setMaxLocals ( ) ;


signature:
public class BcelUtil { /** * Returns the constant string at the specified offset .
 * @ param pool the constant pool
 * @ param index the index in the constant pool
 * @ return the constant string at the specified offset in the constant pool */
public static String getConstantString ( ConstantPool pool , int index ) { } }

implementation: Constant c = pool . getConstant ( index ) ; assert c != null : "Bad index " + index + " into pool" ; if ( c instanceof ConstantUtf8 ) { return ( ( ConstantUtf8 ) c ) . getBytes ( ) ; } else if ( c instanceof ConstantClass ) { ConstantClass cc = ( ConstantClass ) c ; return cc . getBytes ( pool ) + " [" + cc . getNameIndex ( ) + "]" ; } else { throw new Error ( "unexpected constant " + c + " of class " + c . getClass ( ) ) ; }


signature:
public class BcelUtil { /** * Sets the locals to be the formal parameters . Any other locals are removed . An instruction list
 * with at least one instruction must exist .
 * @ param mg the method whose locals to set */
public static void resetLocalsToFormals ( MethodGen mg ) { } }

implementation:
// Get the parameter types and names .
@ SuppressWarnings ( "nullness" // The annotation arguments might not be initialized yet .
// Since the arguments are not executed at run time , there is no null pointer exception .
) Type @ SameLen ( { "argTypes" , "mg.getArgumentTypes()" } ) [ ] argTypes = mg . getArgumentTypes ( ) ; @ SuppressWarnings ( "nullness" // The annotation arguments might not be initialized yet .
// Since the arguments are not executed at run time , there is no null pointer exception .
) String @ SameLen ( { "argTypes" , "argNames" , "mg.getArgumentTypes()" , "mg.getArgumentNames()" } ) [ ] argNames = mg . getArgumentNames ( ) ; // Remove any existing locals
mg . setMaxLocals ( 0 ) ; mg . removeLocalVariables ( ) ; // Add a local for the instance variable ( this )
if ( ! mg . isStatic ( ) ) { mg . addLocalVariable ( "this" , new ObjectType ( mg . getClassName ( ) ) , null , null ) ; } // Add a local for each parameter
for ( int ii = 0 ; ii < argNames . length ; ii ++ ) { mg . addLocalVariable ( argNames [ ii ] , argTypes [ ii ] , null , null ) ; } // Reset the current number of locals so that when other locals
// are added they get added at the correct offset .
mg . setMaxLocals ( ) ; return ;


signature:
public class BcelUtil { /** * Empties the method of all code ( except for a return ) . This includes line numbers , exceptions ,
 * local variables , etc .
 * @ param mg the method to clear out */
public static void makeMethodBodyEmpty ( MethodGen mg ) { } }

implementation: mg . setInstructionList ( new InstructionList ( new RETURN ( ) ) ) ; mg . removeExceptionHandlers ( ) ; mg . removeLineNumbers ( ) ; mg . removeLocalVariables ( ) ; mg . setMaxLocals ( ) ;


signature:
public class BcelUtil { /** * Remove the local variable type table attribute ( LVTT ) from mg . Evidently some changes require
 * this to be updated , but without BCEL support that would be hard to do . It should be safe to
 * just delete it since it is optional and really only of use to a debugger .
 * @ param mg the method to clear out */
public static void removeLocalVariableTypeTables ( MethodGen mg ) { } }

implementation: for ( Attribute a : mg . getCodeAttributes ( ) ) { if ( isLocalVariableTypeTable ( a , mg . getConstantPool ( ) ) ) { mg . removeCodeAttribute ( a ) ; } }


signature:
public class BcelUtil { /** * Returns the Java class name , in the format of { @ link Class # getName ( ) } , that corresponds to
 * type .
 * @ param type the type
 * @ return the Java classname that corresponds to type */
public static @ ClassGetName String typeToClassgetname ( Type type ) { } }

implementation: String signature = type . getSignature ( ) ; return Signatures . fieldDescriptorToClassGetName ( signature ) ;


signature:
public class BcelUtil { /** * Returns the class that corresponds to type .
 * @ param type the type
 * @ return the Java class that corresponds to type */
public static Class < ? > typeToClass ( Type type ) { } }

implementation: String classname = typeToClassgetname ( type ) ; try { return ReflectionPlume . classForName ( classname ) ; } catch ( Exception e ) { throw new RuntimeException ( "can't find class for " + classname , e ) ; }


signature:
public class BcelUtil { /** * Returns a copy of the given type array , with newType added to the end .
 * @ param types the array to extend
 * @ param newType the element to add to the end of the array
 * @ return a new array , with newType at the end */
public static Type [ ] postpendToArray ( Type [ ] types , Type newType ) { } }

implementation: if ( types . length == Integer . MAX_VALUE ) { throw new Error ( "array " + types + " is too large to extend" ) ; } Type [ ] newTypes = new Type [ types . length + 1 ] ; System . arraycopy ( types , 0 , newTypes , 0 , types . length ) ; newTypes [ types . length ] = newType ; return newTypes ;


signature:
public class BcelUtil { /** * Return the type corresponding to a given class name .
 * @ param classname the binary name of a class ( = fully - qualified name , except for inner classes )
 * @ return the type corresponding to the given class name */
public static Type classnameToType ( @ BinaryName String classname ) { } }

implementation:
classname = classname . intern ( ) ; if ( classname == "int" ) { // interned
return Type . INT ; } else if ( classname == "boolean" ) { // interned
return Type . BOOLEAN ; } else if ( classname == "byte" ) { // interned
return Type . BYTE ; } else if ( classname == "char" ) { // interned
return Type . CHAR ; } else if ( classname == "double" ) { // interned
return Type . DOUBLE ; } else if ( classname == "float" ) { // interned
return Type . FLOAT ; } else if ( classname == "long" ) { // interned
return Type . LONG ; } else if ( classname == "short" ) { // interned
return Type . SHORT ; } else { // must be a non - primitive
return new ObjectType ( classname ) ; }


signature:
public class StackTypes { /** * Sets the stack for the instruction at the specified offset to a copy of the information in the
 * given frame .
 * @ param offset the offset at which the instruction appears
 * @ param f the stack frame to use for the instruction */
public void set ( @ IndexFor ( { } }

implementation:
"loc_arr" , "os_arr" } ) int offset , Frame f ) { OperandStack os = f . getStack ( ) ; // logger . info ( " stack [ " + offset + " ] = " + toString ( os ) ) ;
loc_arr [ offset ] = ( LocalVariables ) ( f . getLocals ( ) . clone ( ) ) ; os_arr [ offset ] = ( OperandStack ) ( os . clone ( ) ) ;


signature:
public class JvmUtil { /** * Convert a binary name to a field descriptor . For example , convert " java . lang . Object [ ] " to
 * " [ Ljava / lang / Object ; " or " int " to " I " .
 * @ param classname name of the class , in binary class name format
 * @ return name of the class , in field descriptor format */
@ SuppressWarnings ( "signature" ) // conversion routine
public static @ FieldDescriptor String binaryNameToFieldDescriptor ( @ BinaryName String classname ) { } }

implementation: int dims = 0 ; String sansArray = classname ; while ( sansArray . endsWith ( "[]" ) ) { dims ++ ; sansArray = sansArray . substring ( 0 , sansArray . length ( ) - 2 ) ; } String result = primitiveClassesJvm . get ( sansArray ) ; if ( result == null ) { result = "L" + sansArray + ";" ; } for ( int i = 0 ; i < dims ; i ++ ) { result = "[" + result ; } return result . replace ( '.' , '/' ) ;


signature:
public class JvmUtil { /** * Convert a primitive Java type name ( e . g . , " int " , " double " , etc . ) to a field descriptor ( e . g . ,
 * " I " , " D " , etc . ) .
 * @ param primitiveName name of the type , in Java format
 * @ return name of the type , in field descriptor format
 * @ throws IllegalArgumentException if primitiveName is not a valid primitive type name */
public static @ FieldDescriptor String primitiveTypeNameToFieldDescriptor ( String primitiveName ) { } }

implementation: String result = primitiveClassesJvm . get ( primitiveName ) ; if ( result == null ) { throw new IllegalArgumentException ( "Not the name of a primitive type: " + primitiveName ) ; } return result ;


signature:
public class JvmUtil { /** * Convert from a BinaryName to the format of { @ link Class # getName ( ) } .
 * @ param bn the binary name to convert
 * @ return the class name , in Class . getName format */
@ SuppressWarnings ( "signature" ) // conversion routine
public static @ ClassGetName String binaryNameToClassGetName ( /* BinaryName */
String bn ) { } }

implementation: if ( bn . endsWith ( "[]" ) ) { return binaryNameToFieldDescriptor ( bn ) . replace ( '/' , '.' ) ; } else { return bn ; }


signature:
public class JvmUtil { /** * Convert from a FieldDescriptor to the format of { @ link Class # getName ( ) } .
 * @ param fd the class , in field descriptor format
 * @ return the class name , in Class . getName format */
@ SuppressWarnings ( "signature" ) // conversion routine
public static @ ClassGetName String fieldDescriptorToClassGetName ( /* FieldDescriptor */
String fd ) { } }

implementation: if ( fd . startsWith ( "[" ) ) { return fd . replace ( '/' , '.' ) ; } else { return fieldDescriptorToBinaryName ( fd ) ; }


signature:
public class JvmUtil { /** * Convert a fully - qualified argument list from Java format to JVML format . For example , convert
 * " ( java . lang . Integer [ ] , int , java . lang . Integer [ ] [ ] ) " to
 * " ( [ Ljava / lang / Integer ; I [ [ Ljava / lang / Integer ; ) " .
 * @ param arglist an argument list , in Java format
 * @ return argument list , in JVML format */
public static String arglistToJvm ( String arglist ) { } }

implementation:
if ( ! ( arglist . startsWith ( "(" ) && arglist . endsWith ( ")" ) ) ) { throw new Error ( "Malformed arglist: " + arglist ) ; } String result = "(" ; String commaSepArgs = arglist . substring ( 1 , arglist . length ( ) - 1 ) ; StringTokenizer argsTokenizer = new StringTokenizer ( commaSepArgs , "," , false ) ; while ( argsTokenizer . hasMoreTokens ( ) ) { @ SuppressWarnings ( "signature" ) // substring
@ BinaryName String arg = argsTokenizer . nextToken ( ) . trim ( ) ; result += binaryNameToFieldDescriptor ( arg ) ; } result += ")" ; // System . out . println ( " arglistToJvm : " + arglist + " = > " + result ) ;
return result ;


signature:
public class JvmUtil { /** * Convert a field descriptor to a binary name . For example , convert " [ Ljava / lang / Object ; " to
 * " java . lang . Object [ ] " or " I " to " int " .
 * @ param classname name of the type , in JVML format
 * @ return name of the type , in Java format */
@ SuppressWarnings ( "signature" ) // conversion routine
public static @ BinaryName String fieldDescriptorToBinaryName ( String classname ) { } }

implementation: if ( classname . equals ( "" ) ) { throw new Error ( "Empty string passed to fieldDescriptorToBinaryName" ) ; } int dims = 0 ; while ( classname . startsWith ( "[" ) ) { dims ++ ; classname = classname . substring ( 1 ) ; } String result ; if ( classname . startsWith ( "L" ) && classname . endsWith ( ";" ) ) { result = classname . substring ( 1 , classname . length ( ) - 1 ) ; } else { result = primitiveClassesFromJvm . get ( classname ) ; if ( result == null ) { throw new Error ( "Malformed base class: " + classname ) ; } } for ( int i = 0 ; i < dims ; i ++ ) { result += "[]" ; } return result . replace ( '/' , '.' ) ;


signature:
public class JvmUtil { /** * Convert an argument list from JVML format to Java format . For example , convert
 * " ( [ Ljava / lang / Integer ; I [ [ Ljava / lang / Integer ; ) " to " ( java . lang . Integer [ ] , int ,
 * java . lang . Integer [ ] [ ] ) " .
 * @ param arglist an argument list , in JVML format
 * @ return argument list , in Java format */
public static String arglistFromJvm ( String arglist ) { } }

implementation:
if ( ! ( arglist . startsWith ( "(" ) && arglist . endsWith ( ")" ) ) ) { throw new Error ( "Malformed arglist: " + arglist ) ; } String result = "(" ; @ Positive int pos = 1 ; while ( pos < arglist . length ( ) - 1 ) { if ( pos > 1 ) { result += ", " ; } int nonarrayPos = pos ; while ( arglist . charAt ( nonarrayPos ) == '[' ) { nonarrayPos ++ ; if ( nonarrayPos >= arglist . length ( ) ) { throw new Error ( "Malformed arglist: " + arglist ) ; } } char c = arglist . charAt ( nonarrayPos ) ; if ( c == 'L' ) { int semicolonPos = arglist . indexOf ( ';' , nonarrayPos ) ; if ( semicolonPos == - 1 ) { throw new Error ( "Malformed arglist: " + arglist ) ; } String fieldDescriptor = arglist . substring ( pos , semicolonPos + 1 ) ; result += fieldDescriptorToBinaryName ( fieldDescriptor ) ; pos = semicolonPos + 1 ; } else { String maybe = fieldDescriptorToBinaryName ( arglist . substring ( pos , nonarrayPos + 1 ) ) ; if ( maybe == null ) { // return null ;
throw new Error ( "Malformed arglist: " + arglist ) ; } result += maybe ; pos = nonarrayPos + 1 ; } } return result + ")" ;


signature:
public class InstructionListUtils { /** * Appends the specified instruction to the end of the specified list . Required because for some
 * reason you can ' t directly append jump instructions to the list - - but you can create new ones
 * and append them .
 * @ param il InstructionList to be modified
 * @ param inst Instruction to be appended */
protected final void append_inst ( InstructionList il , Instruction inst ) { } }

implementation:
// System . out . println ( " append _ inst : " + inst . getClass ( ) . getName ( ) ) ;
if ( inst instanceof LOOKUPSWITCH ) { LOOKUPSWITCH ls = ( LOOKUPSWITCH ) inst ; il . append ( new LOOKUPSWITCH ( ls . getMatchs ( ) , ls . getTargets ( ) , ls . getTarget ( ) ) ) ; } else if ( inst instanceof TABLESWITCH ) { TABLESWITCH ts = ( TABLESWITCH ) inst ; il . append ( new TABLESWITCH ( ts . getMatchs ( ) , ts . getTargets ( ) , ts . getTarget ( ) ) ) ; } else if ( inst instanceof IfInstruction ) { IfInstruction ifi = ( IfInstruction ) inst ; il . append ( InstructionFactory . createBranchInstruction ( inst . getOpcode ( ) , ifi . getTarget ( ) ) ) ; } else { il . append ( inst ) ; }


signature:
public class InstructionListUtils { /** * Inserts an instruction list at the beginning of a method .
 * @ param mg MethodGen of method to be modified
 * @ param new _ il InstructionList holding the new code */
protected final void insert_at_method_start ( MethodGen mg , InstructionList new_il ) { } }

implementation:
// Ignore methods with no instructions
InstructionList il = mg . getInstructionList ( ) ; if ( il == null ) { return ; } insert_before_handle ( mg , il . getStart ( ) , new_il , false ) ;


signature:
public class InstructionListUtils { /** * Inserts a new instruction list into an existing instruction list just prior to the indicated
 * instruction handle ( which must be a member of the existing instruction list ) . If new _ il is
 * null , do nothing .
 * @ param mg MethodGen containing the instruction handle
 * @ param ih InstructionHandle indicating where to insert new code
 * @ param new _ il InstructionList holding the new code
 * @ param redirect _ branches flag indicating if branch targets should be moved from ih to new _ il */
protected final void insert_before_handle ( MethodGen mg , InstructionHandle ih , @ Nullable InstructionList new_il , boolean redirect_branches ) { } }

implementation:
if ( new_il == null ) { return ; } // Ignore methods with no instructions
InstructionList il = mg . getInstructionList ( ) ; if ( il == null ) { return ; } boolean at_start = ( ih . getPrev ( ) == null ) ; new_il . setPositions ( ) ; InstructionHandle new_end = new_il . getEnd ( ) ; int new_length = new_end . getPosition ( ) + new_end . getInstruction ( ) . getLength ( ) ; print_stack_map_table ( "Before insert_inst" ) ; debug_instrument . log ( "  insert_inst: %d%n%s%n" , new_il . getLength ( ) , new_il ) ; // Add the new code in front of the instruction handle .
InstructionHandle new_start = il . insert ( ih , new_il ) ; il . setPositions ( ) ; if ( redirect_branches ) { // Move all of the branches from the old instruction to the new start .
il . redirectBranches ( ih , new_start ) ; } // Move other targets to the new start .
if ( ih . hasTargeters ( ) ) { for ( InstructionTargeter it : ih . getTargeters ( ) ) { if ( ( it instanceof LineNumberGen ) && redirect_branches ) { it . updateTarget ( ih , new_start ) ; } else if ( it instanceof LocalVariableGen ) { LocalVariableGen lvg = ( LocalVariableGen ) it ; // If ih is end of local variable range , leave as is .
// If ih is start of local variable range and we are
// at the begining of the method go ahead and change
// start to new _ start . This is to preserve live range
// for variables that are live for entire method .
if ( ( lvg . getStart ( ) == ih ) && at_start ) { it . updateTarget ( ih , new_start ) ; } } else if ( ( it instanceof CodeExceptionGen ) && redirect_branches ) { CodeExceptionGen exc = ( CodeExceptionGen ) it ; if ( exc . getStartPC ( ) == ih ) exc . updateTarget ( ih , new_start ) ; // else if ( exc . getEndPC ( ) = = ih ) leave as is
else if ( exc . getHandlerPC ( ) == ih ) exc . setHandlerPC ( new_start ) ; else System . out . printf ( "Malformed CodeException: %s%n" , exc ) ; } } } // Need to update stack map for change in length of instruction bytes .
// If redirect _ branches is true then we don ' t want to change the
// offset of a stack map that was on the original ih , we want it
// to ' move ' to the new _ start . If we did not redirect the branches
// then we do want any stack map associated with the original ih
// to stay there . The routine update _ stack _ map starts looking for
// a stack map after the location given as its first argument .
// Thus we need to subtract one from this location if the
// redirect _ branches flag is false .
il . setPositions ( ) ; update_stack_map_offset ( new_start . getPosition ( ) - ( redirect_branches ? 0 : 1 ) , new_length ) ; print_il ( new_start , "After update_stack_map_offset" ) ; // We need to see if inserting the additional instructions caused
// a change in the amount of switch instruction padding bytes .
modify_stack_maps_for_switches ( new_start , il ) ;


signature:
public class InstructionListUtils { /** * Print a BCEL instruction list to the debug _ instrument log .
 * @ param start start of the instruction list
 * @ param label a descriptive string for the instruction list */
private void print_il ( InstructionHandle start , String label ) { } }

implementation: if ( debug_instrument . enabled ( ) ) { print_stack_map_table ( label ) ; InstructionHandle tih = start ; while ( tih != null ) { debug_instrument . log ( "inst: %s %n" , tih ) ; if ( tih . hasTargeters ( ) ) { for ( InstructionTargeter it : tih . getTargeters ( ) ) { debug_instrument . log ( "targeter: %s %n" , it ) ; } } tih = tih . getNext ( ) ; } }


signature:
public class InstructionListUtils { /** * Convenience function to build an instruction list .
 * @ param instructions a variable number of BCEL instructions
 * @ return an InstructionList */
protected final InstructionList build_il ( Instruction ... instructions ) { } }

implementation: InstructionList il = new InstructionList ( ) ; for ( Instruction inst : instructions ) { append_inst ( il , inst ) ; } return il ;


signature:
public class InstructionListUtils { /** * Delete instruction ( s ) from start _ ih thru end _ ih in an instruction list . start _ ih may be the
 * first instruction of the list , but end _ ih must not be the last instruction of the list .
 * start _ ih may be equal to end _ ih . There must not be any targeters on any of the instructions to
 * be deleted except for start _ ih . Those targeters will be moved to the first instruction
 * following end _ ih .
 * @ param mg MethodGen containing the instruction handles
 * @ param start _ ih InstructionHandle indicating first instruction to be deleted
 * @ param end _ ih InstructionHandle indicating last instruction to be deleted */
protected final void delete_instructions ( MethodGen mg , InstructionHandle start_ih , InstructionHandle end_ih ) { } }

implementation:
InstructionList il = mg . getInstructionList ( ) ; InstructionHandle new_start = end_ih . getNext ( ) ; if ( new_start == null ) { throw new RuntimeException ( "Cannot delete last instruction." ) ; } il . setPositions ( ) ; int size_deletion = start_ih . getPosition ( ) - new_start . getPosition ( ) ; // Move all of the branches from the first instruction to the new start
il . redirectBranches ( start_ih , new_start ) ; // Move other targeters to the new start .
if ( start_ih . hasTargeters ( ) ) { for ( InstructionTargeter it : start_ih . getTargeters ( ) ) { if ( it instanceof LineNumberGen ) { it . updateTarget ( start_ih , new_start ) ; } else if ( it instanceof LocalVariableGen ) { it . updateTarget ( start_ih , new_start ) ; } else if ( it instanceof CodeExceptionGen ) { CodeExceptionGen exc = ( CodeExceptionGen ) it ; if ( exc . getStartPC ( ) == start_ih ) exc . updateTarget ( start_ih , new_start ) ; else if ( exc . getEndPC ( ) == start_ih ) exc . updateTarget ( start_ih , new_start ) ; else if ( exc . getHandlerPC ( ) == start_ih ) exc . setHandlerPC ( new_start ) ; else System . out . printf ( "Malformed CodeException: %s%n" , exc ) ; } else { System . out . printf ( "unexpected target %s%n" , it ) ; } } } // Remove the old handle ( s ) . There should not be any targeters left .
try { il . delete ( start_ih , end_ih ) ; } catch ( Exception e ) { throw new Error ( "Can't delete instruction list" , e ) ; } // Need to update instruction positions due to delete above .
il . setPositions ( ) ; // Update stack map to account for deleted instructions .
update_stack_map_offset ( new_start . getPosition ( ) , size_deletion ) ; // Check to see if the deletion caused any changes
// in the amount of switch instruction padding bytes .
// If so , we may need to update the corresponding stackmap .
modify_stack_maps_for_switches ( new_start , il ) ;


signature:
public class InstructionListUtils { /** * Compute the StackMapTypes of the live variables of the current method at a specific location
 * within the method . There may be gaps ( " Bogus " or non - live slots ) so we can ' t just count the
 * number of live variables , we must find the max index of all the live variables .
 * @ param mg MethodGen for the current method
 * @ param location the code location to be evaluated
 * @ return an array of StackMapType describing the live locals at location */
protected final StackMapType [ ] calculate_live_local_types ( MethodGen mg , int location ) { } }

implementation: int max_local_index = - 1 ; StackMapType [ ] local_map_types = new StackMapType [ mg . getMaxLocals ( ) ] ; Arrays . fill ( local_map_types , new StackMapType ( Const . ITEM_Bogus , - 1 , pool . getConstantPool ( ) ) ) ; for ( LocalVariableGen lv : mg . getLocalVariables ( ) ) { if ( location >= lv . getStart ( ) . getPosition ( ) ) { if ( lv . getLiveToEnd ( ) || location < lv . getEnd ( ) . getPosition ( ) ) { int i = lv . getIndex ( ) ; local_map_types [ i ] = generate_StackMapType_from_Type ( lv . getType ( ) ) ; max_local_index = Math . max ( max_local_index , i ) ; } } } return Arrays . copyOf ( local_map_types , max_local_index + 1 ) ;


signature:
public class InstructionListUtils { /** * Compute the StackMapTypes of the items on the execution stack as described by the OperandStack
 * argument .
 * @ param stack an OperandStack object
 * @ return an array of StackMapType describing the stack contents */
protected final StackMapType [ ] calculate_live_stack_types ( OperandStack stack ) { } }

implementation: int ss = stack . size ( ) ; StackMapType [ ] stack_map_types = new StackMapType [ ss ] ; for ( int ii = 0 ; ii < ss ; ii ++ ) { stack_map_types [ ii ] = generate_StackMapType_from_Type ( stack . peek ( ss - ii - 1 ) ) ; } return stack_map_types ;