Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
   /*
    * JBoss, Home of Professional Open Source.
    *
    * Copyright 2012 Red Hat, Inc.
    *
    * Licensed under the Apache License, Version 2.0 (the "License");
    * you may not use this file except in compliance with the License.
    * You may obtain a copy of the License at
    *
   *     http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  package org.jboss.classfilewriter.code;
  
  import java.util.HashMap;
  import java.util.List;
  import java.util.Map;
  
  
  public class CodeAttribute extends Attribute {
  
      public static final String NAME = "Code";
  
      private final ClassMethod method;
  
      private final ConstPool constPool;
  
      private final ByteArrayOutputStream finalDataBytes;
  
      private final DataOutputStream data;
  
      private int maxLocals = 0;
  
      private int maxStackDepth = 0;
  
      private final LinkedHashMap<IntegerStackFramestackFrames = new LinkedHashMap<IntegerStackFrame>();

    
maps bytecode offsets to jump locations. As these jump locations where not known when the instruction was written they need to be overwritten when the final bytecode is written out
  
      private final Map<IntegerIntegerjumpLocations = new HashMap<IntegerInteger>();

    
maps bytecode offsets to jump locations. As these jump locations where not known when the instruction was written they need to be overwritten when the final bytecode is written out

These jump locations are 32 bit offsets,

  
      private final Map<IntegerIntegerjumpLocations32 = new HashMap<IntegerInteger>();
  
      private StackFrame currentFrame;
  
      private int currentOffset;
  
      private final List<Attributeattributes = new ArrayList<Attribute>();
  
      //disable for now, as this has some issues
      private boolean stackMapAttributeValid = false;
  
      private final StackMapTableAttribute stackMapTableAttribute;
  
      private final List<ExceptionHandlerexceptionTable = new ArrayList<ExceptionHandler>();
  
      public CodeAttribute(ClassMethod methodConstPool constPool) {
          super(constPool);
          this. = method;
          this. = constPool;
          this. = new ByteArrayOutputStream();
          this. = new DataOutputStream();
  
          if (!Modifier.isStatic(method.getAccessFlags())) {
              ++;
          }
          for (String param : method.getParameters()) {
              if (DescriptorUtils.isWide(param)) {
                  += 2;
             } else {
                 ++;
             }
         }
         // creates a new initial stack frame
          = new StackFrame(method);
         .put(0, );
          = 0;
          = new StackMapTableAttribute(methodconstPool);
     }
 
     @Override
     public void writeData(ByteArrayDataOutputStream streamthrows IOException {
 
         if () {
             // add the stack map table
             .add();
         }
 
         if (.size() == 0) {
             throw new RuntimeException("Code attribute is empty for method " + .getName() + "  " + .getDescriptor());
         }
 
         byte[] bytecode = .toByteArray();
         for (Entry<IntegerIntegere : .entrySet()) {
             overwriteShort(bytecodee.getKey(), e.getValue());
         }
         for (Entry<IntegerIntegere : .entrySet()) {
             overwriteInt(bytecodee.getKey(), e.getValue());
         }
 
         LazySize size = stream.writeSize();
         stream.writeShort();
         stream.writeShort();
         stream.writeInt(bytecode.length);
         stream.write(bytecode);
         stream.writeShort(.size()); // exception table length
         for (ExceptionHandler exception : ) {
             stream.writeShort(exception.getStart());
             stream.writeShort(exception.getEnd());
             stream.writeShort(exception.getHandler());
             stream.writeShort(exception.getExceptionIndex());
         }
         stream.writeShort(.size()); // attributes count
         for (Attribute attribute : ) {
             attribute.write(stream);
         }
         size.markEnd();
         ;
     }
 
     // -------------------------------------------
     // Instruction methods, in alphabetical order
 
     public void aaload() {
         assertTypeOnStack(."aaload requires int on top of stack");
         if (!getStack().top_1().getDescriptor().startsWith("[")) {
             throw new InvalidBytecodeException("aaload needs an array in position 2 on the stack");
         }
         writeByte(.);
         ++;
         advanceFrame(.pop2push1("Ljava/lang/Object;"));
     }
 
     public void aastore() {
         assertTypeOnStack(."aastore requires reference type on top of stack");
         assertTypeOnStack(1, ."aastore requires an int on position 2 stack");
         if (!getStack().top_2().getDescriptor().startsWith("[")) {
             throw new InvalidBytecodeException("aaload needs an array in position 3 on the stack");
         }
         writeByte(.);
         ++;
         advanceFrame(.pop3());
     }
 
     public void aconstNull() {
         writeByte(.);
         ++;
     }
 
     public void aload(int no) {
         LocalVariableState locals = getLocalVars();
         if (locals.size() <= no) {
             throw new InvalidBytecodeException("Cannot load variable at " + no + ". Local Variables: " + locals.toString());
         }
         StackEntry entry = locals.get(no);
         if (entry.getType() != . && entry.getType() != .
                 && entry.getType() != .
                 && entry.getType() != .) {
             throw new InvalidBytecodeException("Invalid local variable at location " + no + " Local Variables "
                     + locals.toString());
         }
 
         if (no > 0xFF) {
             // wide version
             writeByte(.);
             writeByte(.);
             writeShort(no);
              += 4;
         } else if (no >= 0 && no < 4) {
             writeByte(. + no);
             ++;
         } else {
             writeByte(.);
             writeByte(no);
              += 2;
         }
         advanceFrame(.push(entry));
     }
 
     public void anewarray(String arrayType) {
         assertTypeOnStack(."anewarray requires int on stack");
         int index = .addClassEntry(arrayType);
         writeByte(.);
         writeShort(index);
          += 3;
         if (arrayType.startsWith("[")) {
             advanceFrame(.replace("[" + arrayType));
         } else {
             advanceFrame(.replace("[L" + arrayType + ";"));
         }
     }
 
     public void arraylength() {
         assertTypeOnStack(."arraylength requires array on stack");
         writeByte(.);
         ++;
         advanceFrame(.replace("I"));
     }
 
     public void astore(int no) {
         assertTypeOnStack(."aastore requires reference type on stack");
         if (no > 0xFF) {
             // wide version
             writeByte(.);
             writeByte(.);
             writeShort(no);
              += 4;
         } else if (no >= 0 && no < 4) {
             writeByte(. + no);
             ++;
         } else {
             writeByte(.);
             writeByte(no);
              += 2;
         }
         advanceFrame(.store(no));
     }
 
     public void athrow() {
         assertTypeOnStack(."athrow requires an object on the stack");
         writeByte(.);
         ++;
          = null;
     }
 
     public void baload() {
         assertTypeOnStack(."baload requires an int on top of the stack");
         assertTypeOnStack(1, ."baload requires an array in position 2 on the stack");
         writeByte(.);
         ++;
         advanceFrame(.pop2push1("I"));
     }
 
     public void bastore() {
         assertTypeOnStack(."bastore requires an int on top of the stack");
         assertTypeOnStack(1, ."bastore requires an int in position 2 on the stack");
         assertTypeOnStack(2, ."bastore requires an array reference in position 3 on the stack");
         writeByte(.);
         ++;
         advanceFrame(.pop3());
     }
 
     public void caload() {
         assertTypeOnStack(."caload requires an int on top of the stack");
         assertTypeOnStack(1, ."caload requires an array in position 2 on the stack");
         writeByte(.);
         ++;
         advanceFrame(.pop2push1("I"));
     }
 
     public void castore() {
         assertTypeOnStack(."castore requires an int on top of the stack");
         assertTypeOnStack(1, ."castore requires an int in position 2 on the stack");
         assertTypeOnStack(2, ."castore requires an array reference in position 3 on the stack");
         writeByte(.);
         ++;
         advanceFrame(.pop3());
     }
 
     public void bipush(byte value) {
         writeByte(.);
         writeByte(value);
          += 2;
         advanceFrame(.push("B"));
     }

    
marks the end of a branch. The current stack frame is checked for compatibility with the stack frame at the branch start
 
     public void branchEnd(BranchEnd end) {
         mergeStackFrames(end.getStackFrame());
         final int jump =  - end.getOffsetLocation();
         if (end.isJump32Bit()) {
             .put(end.getBranchLocation(), jump);
         } else {
             if(jump > .) {
                 throw new RuntimeException(jump + " is to big to be written as a 16 bit value");
             }
             .put(end.getBranchLocation(), jump);
         }
     }

    
Do not use Descriptor format (e.g. Ljava/lang/Object;), the correct form is just java/lang/Object or java.lang.Object
 
     public void checkcast(String className) {
         assertTypeOnStack(."checkcast requires reference type on stack");
         int classIndex = .addClassEntry(className);
         writeByte(.);
         writeShort(classIndex);
          += 3;
         advanceFrame(.replace(className));
     }
 
     public void checkcast(Class<?> clazz) {
         checkcast(clazz.getName());
     }
 
     public void d2f() {
         assertTypeOnStack(."d2f requires double on stack");
         writeByte(.);
         ++;
         advanceFrame(.pop2push1("F"));
     }
 
     public void d2i() {
         assertTypeOnStack(."d2i requires double on stack");
         writeByte(.);
         ++;
         advanceFrame(.pop2push1("I"));
     }
 
     public void d2l() {
         assertTypeOnStack(."d2l requires double on stack");
         writeByte(.);
         ++;
         advanceFrame(.pop2push1("J"));
     }
 
     public void dadd() {
         assertTypeOnStack(."dadd requires double on stack");
         assertTypeOnStack(2, ."dadd requires double on stack");
         writeByte(.);
         ++;
         advanceFrame(.pop2());
     }
 
     public void daload() {
         assertTypeOnStack(."daload requires an int on top of the stack");
         assertTypeOnStack(1, ."daload requires an array in position 2 on the stack");
         writeByte(.);
         ++;
         advanceFrame(.pop2push1("D"));
     }
 
     public void dastore() {
         assertTypeOnStack(."dastore requires an int on top of the stack");
         assertTypeOnStack(2, ."dastore requires an int in position 2 on the stack");
         assertTypeOnStack(3, ."dastore requires an array reference in position 3 on the stack");
         writeByte(.);
         ++;
         advanceFrame(.pop4());
     }
 
     public void dcmpg() {
         assertTypeOnStack(."dcmpg requires double on stack");
         assertTypeOnStack(2, ."dcmpg requires double on stack");
         writeByte(.);
         ++;
         advanceFrame(.pop4push1("I"));
     }
 
     public void dcmpl() {
         assertTypeOnStack(."dcmpl requires double on stack");
         assertTypeOnStack(2, ."dcmpl requires double in position 3 on stack");
         writeByte(.);
         ++;
         advanceFrame(.pop4push1("I"));
     }

    
Adds the appropriate dconst instruction.

note, if the value is not 0 or 1 then ldc is used instead

 
     public void dconst(double value) {
         if (value == 0.0) {
             writeByte(.);
         } else if (value == 1.0) {
             writeByte(.);
         } else {
             ldc2(value);
             return;
         }
         ++;
         advanceFrame(.push("D"));
     }
 
     public void ddiv() {
         assertTypeOnStack(."ddiv requires double on stack");
         assertTypeOnStack(2, ."ddiv requires double in position 3 on stack");
         writeByte(.);
         ++;
         advanceFrame(.pop2());
     }
 
     public void dload(int no) {
         LocalVariableState locals = getLocalVars();
         if (locals.size() <= no) {
             throw new InvalidBytecodeException("Cannot load variable at " + no + ". Local Variables: " + locals.toString());
         }
         StackEntry entry = locals.get(no);
         if (entry.getType() != .) {
             throw new InvalidBytecodeException("Invalid local variable at location " + no + " Local Variables "
                     + locals.toString());
         }
 
         if (no > 0xFF) {
             // wide version
             writeByte(.);
             writeByte(.);
             writeShort(no);
              += 4;
         } else if (no >= 0 && no < 4) {
             writeByte(. + no);
             ++;
         } else {
             writeByte(.);
             writeByte(no);
              += 2;
         }
         advanceFrame(.push(entry));
     }
 
     public void dmul() {
         assertTypeOnStack(."dmul requires double on stack");
         assertTypeOnStack(2, ."dmul requires double in position 3 on stack");
         writeByte(.);
         ++;
         advanceFrame(.pop2());
     }
 
     public void dneg() {
         assertTypeOnStack(."dneg requires double on stack");
         writeByte(.);
         ++;
         duplicateFrame();
     }
 
     public void drem() {
         assertTypeOnStack(."drem requires double on stack");
         assertTypeOnStack(2, ."drem requires double in position 3 on stack");
         writeByte(.);
         ++;
         advanceFrame(.pop2());
     }
 
     public void dstore(int no) {
         assertTypeOnStack(."dastore requires double on stack");
         if (no > 0xFF) {
             // wide version
             writeByte(.);
             writeByte(.);
             writeShort(no);
              += 4;
         } else if (no >= 0 && no < 4) {
             writeByte(. + no);
             ++;
         } else {
             writeByte(.);
             writeByte(no);
              += 2;
         }
         advanceFrame(.store(no));
     }
 
     public void dsub() {
         assertTypeOnStack(."dsub requires double on stack");
         assertTypeOnStack(2, ."dsub requires double in position 3 on stack");
         writeByte(.);
         ++;
         advanceFrame(.pop2());
     }
 
     public void dup() {
         assertNotWideOnStack("dup acnnot be used if double or long is on top of the stack");
         writeByte(.);
         ++;
         advanceFrame(.dup());
     }
 
     public void dupX1() {
         assertNotWideOnStack("dup_x1 cannot be used if double or long is on top of the stack");
         assertNotWideOnStack(1, "dup_x1 cannot be used if double or long is in position 2 on the stack");
         writeByte(.);
         ++;
         advanceFrame(.dupX1());
     }
 
     public void dupX2() {
         assertNotWideOnStack("dup_x2 acnnot be used if double or long is on top of the stack");
         writeByte(.);
         ++;
         advanceFrame(.dupX2());
     }
 
     public void dup2() {
         writeByte(.);
         ++;
         advanceFrame(.dup2());
     }
 
     public void dup2X1() {
         assertNotWideOnStack(2, "dup2_x1 cannot be used if double or long is in position 3 on the stack");
         writeByte(.);
         ++;
         advanceFrame(.dup2X1());
     }
 
     public void dup2X2() {
         assertNotWideOnStack(3, "dup2_x2 cannot be used if double or long is in position 4 on the stack");
         writeByte(.);
         ++;
         advanceFrame(.dup2X2());
     }

    
Begin writing an exception handler block. The handler is not actually persisted until exceptionHandler is called.
 
     public ExceptionHandler exceptionBlockStart(String exceptionType) {
         ExceptionHandler handler = new ExceptionHandler(.addClassEntry(exceptionType), exceptionType,
                 );
         return handler;
     }

    
Mark the end of an exception handler block. The last instruction that was written will be the last instruction covered by the handler
 
     public void exceptionBlockEnd(ExceptionHandler handler) {
         handler.setEnd();
     }

    
Marks the current code location as the exception handler and adds the handler to the exception handler table;
 
     public void exceptionHandlerStart(ExceptionHandler handler) {
         if (handler.getEnd() == 0) {
             throw new InvalidBytecodeException(
                     "handler end location must be initialised via exceptionHandlerEnd before calling exceptionHandlerAdd");
         }
         handler.setHandler();
         .add(handler);
         mergeStackFrames(new StackFrame(new StackState(handler.getExceptionType(), ), handler.getFrame()
                 .getLocalVariableState(), .));
     }
 
     public void f2d() {
         assertTypeOnStack(."f2s requires float on stack");
         writeByte(.);
         ++;
         advanceFrame(.replace("D"));
     }
 
     public void f2i() {
         assertTypeOnStack(."f2i requires float on stack");
         writeByte(.);
         ++;
         advanceFrame(.replace("I"));
     }
 
     public void f2l() {
         assertTypeOnStack(."f2l requires float on stack");
         writeByte(.);
         ++;
         advanceFrame(.replace("J"));
     }
 
     public void fadd() {
         assertTypeOnStack(."fadd requires float on stack");
         assertTypeOnStack(1, ."fadd requires float on stack");
         writeByte(.);
         ++;
         advanceFrame(.pop());
     }
 
     public void faload() {
         assertTypeOnStack(."faload requires an int on top of the stack");
         assertTypeOnStack(1, ."faload requires an array in position 2 on the stack");
         writeByte(.);
         ++;
         advanceFrame(.pop2push1("F"));
     }
 
     public void fastore() {
         assertTypeOnStack(."fastore requires an int on top of the stack");
         assertTypeOnStack(1, ."fastore requires an int in position 2 on the stack");
         assertTypeOnStack(2, ."fastore requires an array reference in position 3 on the stack");
         writeByte(.);
         ++;
         advanceFrame(.pop3());
     }
 
     public void fcmpg() {
         assertTypeOnStack(."fcmpg requires float on stack");
         assertTypeOnStack(1, ."fcmpg requires float on stack");
         writeByte(.);
         ++;
         advanceFrame(.pop2push1("I"));
     }
 
     public void fcmpl() {
         assertTypeOnStack(."fcmpl requires float on stack");
         assertTypeOnStack(1, ."fcmpl requires float in position 2 on stack");
         writeByte(.);
         ++;
         advanceFrame(.pop2push1("I"));
     }

    
Adds the appropriate fconst instruction.

note, if the value is not 0, 1, 2 then ldc is used instead

 
     public void fconst(float value) {
         if (value == 0) {
             writeByte(.);
         } else if (value == 1) {
             writeByte(.);
         } else if (value == 2) {
             writeByte(.);
         } else {
             ldc(value);
             return;
         }
         ++;
         advanceFrame(.push("F"));
     }
 
     public void fdiv() {
         assertTypeOnStack(."fdiv requires float on stack");
         assertTypeOnStack(1, ."fdiv requires float in position 2 on stack");
         writeByte(.);
         ++;
         advanceFrame(.pop());
     }
 
     public void fload(int no) {
         LocalVariableState locals = getLocalVars();
         if (locals.size() <= no) {
             throw new InvalidBytecodeException("Cannot load variable at " + no + ". Local Variables: " + locals.toString());
         }
         StackEntry entry = locals.get(no);
         if (entry.getType() != .) {
             throw new InvalidBytecodeException("Invalid local variable at location " + no + " Local Variables "
                     + locals.toString());
         }
 
         if (no > 0xFF) {
             // wide version
             writeByte(.);
             writeByte(.);
             writeShort(no);
              += 4;
         } else if (no >= 0 && no < 4) {
             writeByte(. + no);
             ++;
         } else {
             writeByte(.);
             writeByte(no);
              += 2;
         }
         advanceFrame(.push(entry));
     }
 
     public void fmul() {
         assertTypeOnStack(."fmul requires float on stack");
         assertTypeOnStack(1, ."fmul requires float in position 2 on stack");
         writeByte(.);
         ++;
         advanceFrame(.pop());
     }
 
     public void fneg() {
         assertTypeOnStack(."fneg requires float on stack");
         writeByte(.);
         ++;
         duplicateFrame();
     }
 
     public void frem() {
         assertTypeOnStack(."frem requires float on stack");
         assertTypeOnStack(1, ."frem requires float in position 2 on stack");
         writeByte(.);
         ++;
         advanceFrame(.pop());
     }
 
     public void fstore(int no) {
         assertTypeOnStack(."fstore requires float on stack");
         if (no > 0xFF) {
             // wide version
             writeByte(.);
             writeByte(.);
             writeShort(no);
              += 4;
         } else if (no >= 0 && no < 4) {
             writeByte(. + no);
             ++;
         } else {
             writeByte(.);
             writeByte(no);
              += 2;
         }
         advanceFrame(.store(no));
     }
 
     public void fsub() {
         assertTypeOnStack(."fsub requires float on stack");
         assertTypeOnStack(1, ."fsub requires float in position 2 on stack");
         writeByte(.);
         ++;
         advanceFrame(.pop());
     }
 
     public void getfield(String classNameString fieldClass<?> fieldType) {
         getfield(classNamefield, DescriptorUtils.makeDescriptor(fieldType));
     }
 
     public void getfield(String classNameString fieldString descriptor) {
         assertTypeOnStack(."getfield requires object on stack");
         int index = .addFieldEntry(classNamefielddescriptor);
         writeByte(.);
         writeShort(index);
          += 3;
         advanceFrame(.replace(descriptor));
     }
 
     public void getstatic(String classNameString fieldClass<?> fieldType) {
         getstatic(classNamefield, DescriptorUtils.makeDescriptor(fieldType));
     }
 
     public void getstatic(String classNameString fieldString descriptor) {
         int index = .addFieldEntry(classNamefielddescriptor);
         writeByte(.);
         writeShort(index);
          += 3;
         advanceFrame(.push(descriptor));
     }

    
writes a goto instruction.

TODO: implemented goto_w

 
     public void gotoInstruction(CodeLocation location) {
         writeByte(.);
         writeShort(location.getLocation() - );
         mergeStackFrames(location.getStackFrame());
          += 3;
          = null;
     }

    
writes a goto instruction.

TODO: implemented goto_w

 
     public BranchEnd gotoInstruction() {
         writeByte(.);
         writeShort(0);
          += 3;
         BranchEnd ret = new BranchEnd( - 2,  - 3);
          = null;
         return ret;
     }
 
     public void i2b() {
         assertTypeOnStack(."i2b requires int on stack");
         writeByte(.);
         ++;
         advanceFrame(.replace("B"));
     }
 
     public void i2c() {
         assertTypeOnStack(."i2c requires int on stack");
         writeByte(.);
         ++;
         advanceFrame(.replace("C"));
     }
 
     public void i2d() {
         assertTypeOnStack(."i2d requires int on stack");
         writeByte(.);
         ++;
         advanceFrame(.replace("D"));
     }
 
     public void i2f() {
         assertTypeOnStack(."i2f requires int on stack");
         writeByte(.);
         ++;
         advanceFrame(.replace("F"));
     }
 
     public void i2l() {
         assertTypeOnStack(."i2l requires int on stack");
         writeByte(.);
         ++;
         advanceFrame(.replace("J"));
     }
 
     public void i2s() {
         assertTypeOnStack(."i2s requires int on stack");
         writeByte(.);
         ++;
         advanceFrame(.replace("S"));
     }
 
     public void iadd() {
         assertTypeOnStack(."iadd requires int on stack");
         assertTypeOnStack(1, ."iadd requires int on stack");
         writeByte(.);
         ++;
         advanceFrame(.pop());
     }
 
     public void iaload() {
         assertTypeOnStack(."iaload requires an int on top of the stack");
         assertTypeOnStack(1, ."iaload requires an array in position 2 on the stack");
         writeByte(.);
         ++;
         advanceFrame(.pop2push1("I"));
     }
 
     public void iand() {
         assertTypeOnStack(."iand requires int on stack");
         assertTypeOnStack(1, ."iand requires int on stack");
         writeByte(.);
         ++;
         advanceFrame(.pop());
     }
 
     public void iastore() {
         assertTypeOnStack(."iastore requires an int on top of the stack");
         assertTypeOnStack(1, ."iastore requires an int in position 2 on the stack");
         assertTypeOnStack(2, ."iastore requires an array reference in position 3 on the stack");
         writeByte(.);
         ++;
         advanceFrame(.pop3());
     }

    
Adds the appropriate iconst instruction.

note, if the value is not in the range -1 to 5 ldc is written instead

Parameters:
value
 
     public void iconst(int value) {
         if (value < -1 || value > 5) {
             if(value < -128 || value > 127) {
                 ldc(value);
             } else {
                 writeByte(.);
                 writeByte(value);
                 +=2;
                 advanceFrame(.push("I"));
             }
             return;
         }
         writeByte(. + value);
         ++;
         advanceFrame(.push("I"));
     }
 
     public void idiv() {
         assertTypeOnStack(."idiv requires int on stack");
         assertTypeOnStack(1, ."idiv requires int in position 2 on stack");
         writeByte(.);
         ++;
         advanceFrame(.pop());
     }
 
     public void ifAcmpeq(CodeLocation location) {
         assertTypeOnStack(."ifAcmpeq requires reference type on stack");
         assertTypeOnStack(1, ."ifAcmpeq requires reference type in position 2 on stack");
         writeByte(.);
         writeShort(location.getLocation() - );
         mergeStackFrames(location.getStackFrame());
          += 3;
         advanceFrame(.pop2());
     }
 
     public BranchEnd ifAcmpeq() {
         assertTypeOnStack(."ifAcmpeq requires reference type on stack");
         assertTypeOnStack(1, ."ifAcmpeq requires reference type int position 2 on stack");
         writeByte(.);
         writeShort(0);
          += 3;
         advanceFrame(.pop2());
         BranchEnd ret = new BranchEnd( - 2,  - 3);
         return ret;
     }
 
     public void ifAcmpne(CodeLocation location) {
         assertTypeOnStack(."ifAcmpne requires reference type on stack");
         assertTypeOnStack(1, ."ifAcmpne requires refer