emma

       leaders.add(ip + ov);
        
        int low = code[(++scan)] << 24 | (0xFF & code[(++scan)]) << 16 | (0xFF & code[(++scan)]) << 8 | 0xFF & code[(++scan)];
        
        int high = code[(++scan)] << 24 | (0xFF & code[(++scan)]) << 16 | (0xFF & code[(++scan)]) << 8 | 0xFF & code[(++scan)];
        
        int[] targets = new int[high - low + 2];
        targets[0] = (ip + ov);
        for (int index = low; index <= high; index++)
        {
          ov = code[(++scan)] << 24 | (0xFF & code[(++scan)]) << 16 | (0xFF & code[(++scan)]) << 8 | 0xFF & code[(++scan)];
          targets[(index - low + 1)] = (ip + ov);
          leaders.add(ip + ov);
        }
        branches.put(ip, new TABLESWITCH(low, high, targets));
        branch = true;
        
        size = ip - scan - 1;
        
        break;
      case 200: 
      case 201: 
        int scan = ip + 1;
        
        int ov = code[scan] << 24 | (0xFF & code[(++scan)]) << 16 | (0xFF & code[(++scan)]) << 8 | 0xFF & code[(++scan)];
        int target = ip + ov;
        
        leaders.add(target);
        
        branches.put(ip, new JUMP4(opcode, target));
        branch = true;
        
        break;
      case 169: 
        int scan = ip + 1;
        int iv = wide ? (0xFF & code[scan]) << 8 | 0xFF & code[(++scan)] : 0xFF & code[scan];
        
        branches.put(ip, new RET(opcode, iv));
        branch = true;
        
        break;
      case 172: 
      case 173: 
      case 174: 
      case 175: 
      case 176: 
      case 177: 
      case 191: 
        branches.put(ip, new TERMINATE(opcode));
        branch = true;
      }
      if (size == 0) {
        size = IOpcodes.NARROW_SIZE[opcode];
      } else {
        size = -size;
      }
      ip += size;
      wide = opcode == 196;
      
      instructionMap.put(ip, ++instructionCount);
    }
    int blockCount = leaders.size();
    if (trace2) {
      m_log.trace2("visit", "method contains " + blockCount + " basic blocks");
    }
    BlockList blocks = new BlockList(blockCount);
    
    int[] _leaders = new int[blockCount + 1];
    leaders.values(_leaders, 0);
    _leaders[blockCount] = codeSize;
    
    Arrays.sort(_leaders);
    
    int[] _branch_locations = branches.keys();
    Arrays.sort(_branch_locations);
    
    IntIntMap leaderToBlockID = new IntIntMap(_leaders.length);
    if (m_metadata)
    {
      m_methodBlockSizes = new int[blockCount];
      m_methodBlockOffsets = _leaders;
    }
    consumeSignatureData(m_methodID, _leaders);
    
    int[] intHolder = new int[1];
    int instr_count = 0;
    
    int bl = 0;
    for (int br = 0; bl < blockCount; bl++)
    {
      Block block = new Block(null);
      m_blocks.add(block);
      
      int leader = _leaders[bl];
      
      m_first = leader;
      leaderToBlockID.put(leader, bl);
      
      int next_leader = _leaders[(bl + 1)];
      boolean branchDelimited = false;
      
      int prev_instr_count = instr_count;
      if (_branch_locations.length > br)
      {
        int next_branch_location = _branch_locations[br];
        if (next_branch_location < next_leader)
        {
          branchDelimited = true;
          
          m_length = (next_branch_location - leader);
          
          instructionMap.get(next_branch_location, intHolder);
          
          instr_count = intHolder[0] + 1;
          
          m_branch = ((Branch)branches.get(next_branch_location));
          m_branch.m_parentBlockID = bl;
          
          br++;
        }
      }
      if (!branchDelimited)
      {
        m_length = (next_leader - leader);
        
        instructionMap.get(next_leader, intHolder);
        
        instr_count = intHolder[0];
      }
      m_instrCount = (instr_count - prev_instr_count);
      if (m_metadata) {
        m_methodBlockSizes[bl] = m_instrCount;
      }
    }
    Block[] _blocks = (Block[])m_blocks.toArray(new Block[blockCount]);
    for (int l = 0; l < blockCount; l++)
    {
      Block block = _blocks[l];
      if (m_branch != null)
      {
        int[] targets = m_branch.m_targets;
        if (targets != null)
        {
          int t = 0;
          for (int targetCount = targets.length; t < targetCount; t++)
          {
            leaderToBlockID.get(targets[t], intHolder);
            
            targets[t] = intHolder[0];
          }
        }
      }
    }
    m_classBlockCounts[m_methodID] = blockCount;
    if (trace2) {
      m_log.trace2("visit", "instrumenting... ");
    }
    int localVarIndex = m_max_locals++;
    if (m_methodID == m_clinitID)
    {
      m_stampIndex = m_cls.getConstants().add(new CONSTANT_Long_info(m_classSignature));
      
      m_header = new clinitHeader(this, localVarIndex);
    }
    else
    {
      m_header = new methodHeader(this, localVarIndex);
    }
    int headerMaxStack = m_header.maxstack();
    int methodMaxStack = 0;
    for (int l = 0; l < blockCount; l++)
    {
      Block block = _blocks[l];
      
      CodeSegment insertion = new BlockSegment(this, localVarIndex, l);
      m_insertion = insertion;
      
      int insertionMaxStack = insertion.maxstack();
      if (insertionMaxStack > methodMaxStack) {
        methodMaxStack = insertionMaxStack;
      }
    }
    int oldMaxStack = m_max_stack;
    
    m_max_stack += methodMaxStack;
    if (headerMaxStack > m_max_stack) {
      m_max_stack = headerMaxStack;
    }
    if (trace3) {
      m_log.trace3("visit", "increasing maxstack by " + (m_max_stack - oldMaxStack));
    }
    if (trace2) {
      m_log.trace2("visit", "assembling... ");
    }
    int newcodeCapacity = codeSize << 1;
    if (newcodeCapacity < 64) {
      newcodeCapacity = 64;
    }
    ByteArrayOStream newcode = new ByteArrayOStream(newcodeCapacity);
    EmitCtx emitctx = new EmitCtx(blocks, newcode);
    
    int[] jumpAdjOffsets = new int[blockCount];
    int[] jumpAdjMap = new int[jumpAdjOffsets.length];
    
    m_header.emit(emitctx);
    
    jumpAdjMap[0] = m_out.size();
    for (int l = 0; l < blockCount; l++)
    {
      Block block = _blocks[l];
      if (l + 1 < blockCount) {
        jumpAdjOffsets[(l + 1)] = (m_first + m_length);
      }
      block.emit(emitctx, code);
      if (l + 1 < blockCount) {
        jumpAdjMap[(l + 1)] = (m_out.size() - 1m_first);
      }
    }
    m_methodJumpAdjOffsets = jumpAdjOffsets;
    m_methodJumpAdjValues = jumpAdjMap;
    if (trace3)
    {
      StringBuffer s = new StringBuffer("jump adjustment map:" + IConstants.EOL);
      for (int a = 0; a < jumpAdjOffsets.length; a++)
      {
        s.append("    " + jumpAdjOffsets[a] + ": +" + jumpAdjMap[a]);
        if (a < jumpAdjOffsets.length - 1) {
          s.append(IConstants.EOL);
        }
      }
      m_log.trace3("visit", s.toString());
    }
    byte[] _newcode = newcode.getByteArray();
    int _newcodeSize = newcode.size();
    if (trace3) {
      m_log.trace3("visit", "backpatching " + m_backpatchQueue.size() + " ip(s)");
    }
    for (Iterator i = m_backpatchQueue.iterator(); i.hasNext();)
    {
      int[] patchData = (int[])i.next();
      int ip = patchData[1];
      
      int jump = 3m_first - patchData[2];
      switch (patchData[0])
      {
      case 4: 
        _newcode[(ip++)] = ((byte)(jump >>> 24));
        _newcode[(ip++)] = ((byte)(jump >>> 16));
      case 2: 
        _newcode[(ip++)] = ((byte)(jump >>> 8));
        _newcode[ip] = ((byte)jump);
      }
    }
    attribute.setCode(_newcode, _newcodeSize);
    if (trace2) {
      m_log.trace2("visit", "method assembled into " + _newcodeSize + " code bytes");
    }
    IExceptionHandlerTable exceptionTable = attribute.getExceptionTable();
    for (int e = 0; e < exceptionTable.size(); e++)
    {
      Exception_info exception = exceptionTable.get(e);
      
      int adjSegment = lowbound(jumpAdjOffsets, m_start_pc);
      m_start_pc += jumpAdjMap[adjSegment];
      
      adjSegment = lowbound(jumpAdjOffsets, m_end_pc);
      m_end_pc += jumpAdjMap[adjSegment];
      
      adjSegment = lowbound(jumpAdjOffsets, m_handler_pc);
      m_handler_pc += jumpAdjMap[adjSegment];
    }
    IAttributeCollection attributes = attribute.getAttributes();
    int attributeCount = attributes.size();
    for (int a = 0; a < attributeCount; a++)
    {
      Attribute_info nested = attributes.get(a);
      nested.accept(this, ctx);
    }
    return ctx;
  }
  
  public Object visit(LineNumberTableAttribute_info attribute, Object ctx)
  {
    boolean trace2 = m_log.atTRACE2();
    boolean trace3 = m_log.atTRACE3();
    if (trace2) {
      m_log.trace2("visit", "attribute: [" + attribute.getName(m_cls) + "]");
    }
    int lineCount = attribute.size();
    if (m_metadata)
    {
      if (trace2) {
        m_log.trace2("visit", "processing line number table for metadata...");
      }
      int blockCount = m_classBlockCounts[m_methodID];
      
      int[][] blockLineMap = new int[blockCount][];
      if (lineCount == 0)
      {
        for (int bl = 0; bl < blockCount; bl++) {
          blockLineMap[bl] = IConstants.EMPTY_INT_ARRAY;
        }
      }
      else
      {
        LineNumber_info[] sortedLines = new LineNumber_info[attribute.size()];
        for (int l = 0; l < lineCount; l++)
        {
          LineNumber_info line = attribute.get(l);
          sortedLines[l] = line;
        }
        Arrays.sort(sortedLines, LINE_NUMBER_COMPARATOR);
        
        int[] methodBlockOffsets = m_methodBlockOffsets;
        
        LineNumber_info line = sortedLines[0];
        LineNumber_info prev_line = null;
        
        m_methodFirstLine = m_line_number;
        
        int bl = 0;
        for (int l = 0; bl < blockCount; bl++)
        {
          IntSet blockLines = new IntSet();
          if ((prev_line != null) && (m_start_pc > methodBlockOffsets[bl])) {
            blockLines.add(m_line_number);
          }
          while (m_start_pc < methodBlockOffsets[(bl + 1)])
          {
            blockLines.add(m_line_number);
            if (l == lineCount - 1) {
              break;
            }
            prev_line = line;
            line = sortedLines[(++l)];
          }
          blockLineMap[bl] = blockLines.values();
        }
      }
      m_classBlockMetadata[m_methodID] = blockLineMap;
      if (trace3)
      {
        StringBuffer s = new StringBuffer("block-line map for method #" + m_methodID + ":");
        for (int bl = 0; bl < blockCount; bl++)
        {
          s.append(IConstants.EOL);
          s.append("    block " + bl + ": ");
          
          int[] lines = blockLineMap[bl];
          for (int l = 0; l < lines.length; l++)
          {
            if (l != 0) {
              s.append(", ");
            }
            s.append(lines[l]);
          }
        }
        m_log.trace3("visit", s.toString());
      }
    }
    for (int l = 0; l < lineCount; l++)
    {
      LineNumber_info line = attribute.get(l);
      
      int adjSegment = lowbound(m_methodJumpAdjOffsets, m_start_pc);
      m_start_pc += m_methodJumpAdjValues[adjSegment];
    }
    return ctx;
  }
  
  public Object visit(ExceptionsAttribute_info attribute, Object ctx)
  {
    return ctx;
  }
  
  public Object visit(ConstantValueAttribute_info attribute, Object ctx)
  {
    return ctx;
  }
  
  public Object visit(SourceFileAttribute_info attribute, Object ctx)
  {
    m_classSrcFileName = getSourceFilem_cls).m_value;
    
    return ctx;
  }
  
  public Object visit(SyntheticAttribute_info attribute, Object ctx)
  {
    return ctx;
  }
  
  public Object visit(BridgeAttribute_info attribute, Object ctx)
  {
    return ctx;
  }
  
  public Object visit(InnerClassesAttribute_info attribute, Object ctx)
  {
    return ctx;
  }
  
  public Object visit(GenericAttribute_info attribute, Object ctx)
  {
    return ctx;
  }
  
  public static final class InstrResult
  {
    public boolean m_instrumented;
    public ClassDescriptor m_descriptor;
  }
  
  private static final class BlockList
  {
    final List m_blocks;
    InstrVisitor.CodeSegment m_header;
    
    BlockList()
    {
      m_blocks = new ArrayList();
    }
    
    BlockList(int capacity)
    {
      m_blocks = new ArrayList(capacity);
    }
  }
  
  private static final class Block
  {
    int m_first;
    int m_length;
    int m_instrCount;
    public InstrVisitor.CodeSegment m_insertion;
    public InstrVisitor.Branch m_branch;
    
    Block(InstrVisitor.1 x0)
    {
      this();
    }
    
    void emit(InstrVisitor.EmitCtx ctx, byte[] code)
    {
      ByteArrayOStream out = m_out;
      int first = m_first;
      
      m_first = out.size();
      
      int i = 0;
      for (int length = m_length; i < length; i++) {
        out.write(code[(first + i)]);
      }
      if (m_insertion != null) {
        m_insertion.emit(ctx);
      }
      if (m_branch != null) {
        m_branch.emit(ctx);
      }
    }
    
    private Block() {}
  }
  
  static final class EmitCtx
  {
    final InstrVisitor.BlockList m_blocks;
    final ByteArrayOStream m_out;
    final List m_backpatchQueue;
    
    EmitCtx(InstrVisitor.BlockList blocks, ByteArrayOStream out)
    {
      m_blocks = blocks;
      m_out = out;
      
      m_backpatchQueue = new ArrayList();
    }
  }
  
  static abstract class Branch
  {
    final byte m_opcode;
    final int[] m_targets;
    int m_parentBlockID;
    
    protected Branch(int opcode, int[] targets)
    {
      m_opcode = ((byte)opcode);
      m_targets = targets;
    }
    
    int maxlength()
    {
      return 1;
    }
    
    abstract void emit(InstrVisitor.EmitCtx paramEmitCtx);
    
    protected final void emitJumpOffset2(InstrVisitor.EmitCtx ctx, int ip, int targetBlockID)
    {
      ByteArrayOStream out = m_out;
      if (targetBlockID <= m_parentBlockID)
      {
        int jumpOffset = m_blocks.m_blocks.get(targetBlockID)).m_first - ip;
        
        out.write2(jumpOffset >>> 8, jumpOffset);
      }
      else
      {
        int jumpOffsetLocation = out.size();
        
        out.write2(0, 0);
        
        m_backpatchQueue.add(new int[] { 2, jumpOffsetLocation, ip, targetBlockID });
      }
    }
    
    protected final void emitJumpOffset4(InstrVisitor.EmitCtx ctx, int ip, int targetBlockID)
    {
      ByteArrayOStream out = m_out;
      if (targetBlockID <= m_parentBlockID)
      {
        int jumpOffset = m_blocks.m_blocks.get(targetBlockID)).m_first - ip;
        
        out.write4(jumpOffset >>> 24, jumpOffset >>> 16, jumpOffset >>> 8, jumpOffset);
      }
      else
      {
        int jumpOffsetLocation = out.size();
        
        out.write4(0, 0, 0, 0);
        
        m_backpatchQueue.add(new int[] { 4, jumpOffsetLocation, ip, targetBlockID });
      }
    }
  }
  
  static final class TERMINATE
    extends InstrVisitor.Branch
  {
    TERMINATE(int opcode)
    {
      super(null);
    }
    
    int length()
    {
      return 1;
    }
    
    void emit(InstrVisitor.EmitCtx ctx)
    {
      m_out.write(m_opcode);
    }
  }
  
  static final class RET
    extends InstrVisitor.Branch
  {
    final int m_varindex;
    
    RET(int opcode, int varindex)
    {
      super(null);
      m_varindex = varindex;
    }
    
    int length()
    {
      return m_varindex <= 255 ? 2 : 3;
    }
    
    void emit(InstrVisitor.EmitCtx ctx)
    {
      ByteArrayOStream out = m_out;
      if (m_varindex <= 255) {
        out.write2(m_opcode, m_varindex);
      } else {
        out.write4(196, m_opcode, m_varindex >>> 8, m_varindex);
      }
    }
  }
  
  static final class JUMP2
    extends InstrVisitor.Branch
  {
    JUMP2(int opcode, int target)
    {
      super(new int[] { target });
    }
    
    int maxlength()
    {
      return 5;
    }
    
    void emit(InstrVisitor.EmitCtx ctx)
    {
      ByteArrayOStream out = m_out;
      int targetBlockID = m_targets[0];
      int ip = out.size();
      
      out.write(m_opcode);
      emitJumpOffset2(ctx, ip, targetBlockID);
    }
  }
  
  static final class JUMP4
    extends InstrVisitor.Branch
  {
    JUMP4(int opcode, int target)
    {
      super(new int[] { target });
    }
    
    int maxlength()
    {
      return 5;
    }
    
    void emit(InstrVisitor.EmitCtx ctx)
    {
      ByteArrayOStream out = m_out;
      int targetBlockID = m_targets[0];
      int ip = out.size();
      
      out.write(m_opcode);
      emitJumpOffset4(ctx, ip, targetBlockID);
    }
  }
  
  static final class IFJUMP2
    extends InstrVisitor.Branch
  {
    IFJUMP2(int opcode, int target)
    {
      super(new int[] { target });
    }
    
    int maxlength()
    {
      return 8;
    }
    
    void emit(InstrVisitor.EmitCtx ctx)
    {
      ByteArrayOStream out = m_out;
      int targetBlockID = m_targets[0];
      int ip = out.size();
      
      out.write(m_opcode);
      emitJumpOffset2(ctx, ip, targetBlockID);
    }
  }
  
  static final class LOOKUPSWITCH
    extends InstrVisitor.Branch
  {
    final int[] m_keys;
    
    LOOKUPSWITCH(int[] keys, int[] targets)
    {
      super(targets);
      m_keys = keys;
    }
    
    int maxlength()
    {
      return 12 + (m_keys.length << 3);
    }
    
    void emit(InstrVisitor.EmitCtx ctx)
    {
      ByteArrayOStream out = m_out;
      int ip = out.size();
      
      out.write(m_opcode);
      
      int p = 0;
      for (int padCount = 3 - (ip & 0x3); p < padCount; p++) {
        out.write(0);
      }
      emitJumpOffset4(ctx, ip, m_targets[0]);
      
      int npairs = m_keys.length;
      out.write4(npairs >>> 24, npairs >>> 16, npairs >>> 8, npairs);
      for (int t = 1; t < m_targets.length; t++)
      {
        int key = m_keys[(t - 1)];
        out.write4(key >>> 24, key >>> 16, key >>> 8, key);
        
        emitJumpOffset4(ctx, ip, m_targets[t]);
      }
    }
  }
  
  static final class TABLESWITCH
    extends InstrVisitor.Branch
  {
    final int m_low;
    final int m_high;
    
    TABLESWITCH(int low, int high, int[] targets)
    {
      super(targets);
      m_low = low;
      m_high = high;
    }
    
    int maxlength()
    {
      return 12 + (m_targets.length << 2);
    }
    
    void emit(InstrVisitor.EmitCtx ctx)
    {
      ByteArrayOStream out = m_out;
      int ip = out.size();
      
      out.write(m_opcode);
      
      int p = 0;
      for (int padCount = 3 - (ip & 0x3); p < padCount; p++) {
        out.write(0);
      }
      emitJumpOffset4(ctx, ip, m_targets[0]);
      
      int low = m_low;
      out.write4(low >>> 24, low >>> 16, low >>> 8, low);
      
      int high = m_high;
      out.write4(high >>> 24, high >>> 16, high >>> 8, high);
      for (int t = 1; t < m_targets.length; t++) {
        emitJumpOffset4(ctx, ip, m_targets[t]);
      }
    }
  }
  
  static abstract class CodeSegment
  {
    final InstrVisitor m_visitor;
    
    CodeSegment(InstrVisitor visitor)
    {
      m_visitor = visitor;
    }
    
    abstract int length();
    
    abstract int maxstack();
    
    abstract void emit(InstrVisitor.EmitCtx paramEmitCtx);
  }
  
  static final class clinitHeader
    extends InstrVisitor.CodeSegment
  {
    private final ByteArrayOStream m_buf;
    private static final int CLINIT_HEADER_INIT_CAPACITY = 32;
    
    clinitHeader(InstrVisitor visitor, int localVarIndex)
    {
      super();
      ByteArrayOStream buf = new ByteArrayOStream(32);
      m_buf = buf;
      
      ClassDef cls = m_cls;
      
      int[] blockCounts = m_classBlockCounts;
      int instrMethodCount = m_classInstrMethodCount;
      
      int coverageFieldrefIndex = m_coverageFieldrefIndex;
      int preclinitMethodrefIndex = m_preclinitMethodrefIndex;
      int classNameConstantIndex = m_classNameConstantIndex;
      
      buf.write3(184, preclinitMethodrefIndex >>> 8, preclinitMethodrefIndex);
      
      CodeGen.push_int_value(buf, cls, m_methodID);
      
      buf.write(50);
      
      CodeGen.store_local_object_var(buf, localVarIndex);
    }
    
    int length()
    {
      return m_buf.size();
    }
    
    int maxstack()
    {
      return 2;
    }
    
    void emit(InstrVisitor.EmitCtx ctx)
    {
      try
      {
        m_buf.writeTo(m_out);
      }
      catch (IOException ioe) {}
    }
  }
  
  static final class methodHeader
    extends InstrVisitor.CodeSegment
  {
    private final ByteArrayOStream m_buf;
    private static final int HEADER_INIT_CAPACITY = 16;
    
    methodHeader(InstrVisitor visitor, int localVarIndex)
    {
      super();
      ByteArrayOStream buf = new ByteArrayOStream(16);
      m_buf = buf;
      
      ClassDef cls = m_cls;
      int coverageFieldrefIndex = m_coverageFieldrefIndex;
      int preclinitMethodrefIndex = m_preclinitMethodrefIndex;
      
      buf.write4(178, coverageFieldrefIndex >>> 8, coverageFieldrefIndex, 89);
      
      buf.write3(199, 0, 7);
      
      buf.write4(87, 184, preclinitMethodrefIndex >>> 8, preclinitMethodrefIndex);
      
      CodeGen.push_int_value(buf, cls, m_methodID);
      
      buf.write(50);
      
      CodeGen.store_local_object_var(buf, localVarIndex);
    }
    
    int length()
    {
      return m_buf.size();
    }
    
    int maxstack()
    {
      return 2;
    }
    
    void emit(InstrVisitor.EmitCtx ctx)
    {
      try
      {
        m_buf.writeTo(m_out);
      }
      catch (IOException ioe) {}
    }
  }
  
  static final class BlockSegment
    extends InstrVisitor.CodeSegment
  {
    private final ByteArrayOStream m_buf;
    private static final int BLOCK_INIT_CAPACITY = 16;
    
    public BlockSegment(InstrVisitor visitor, int localVarIndex, int blockID)
    {
      super();
      ByteArrayOStream buf = new ByteArrayOStream(16);
      m_buf = buf;
      
      ClassDef cls = m_cls;
      
      CodeGen.load_local_object_var(buf, localVarIndex);
      
      CodeGen.push_int_value(buf, cls, blockID);
      
      buf.write2(4, 84);
    }
    
    int length()
    {
      return m_buf.size();
    }
    
    int maxstack()
    {
      return 3;
    }
    
    void emit(InstrVisitor.EmitCtx ctx)
    {
      try
      {
        m_buf.writeTo(m_out);
      }
      catch (IOException ioe) {}
    }
  }
  
  private static final class LineNumberComparator
    implements Comparator
  {
    LineNumberComparator(InstrVisitor.1 x0)
    {
      this();
    }
    
    public final int compare(Object o1, Object o2)
    {
      return m_start_pc - m_start_pc;
    }
    
    private LineNumberComparator() {}
  }
  
  private void setClassName(String fullName)
  {
    int lastSlash = fullName.lastIndexOf('/');
    if (lastSlash < 0)
    {
      m_classPackageName = "";
      m_className = fullName;
    }
    else
    {
      m_classPackageName = fullName.substring(0, lastSlash);
      m_className = fullName.substring(lastSlash + 1);
    }
  }
  
  private void consumeSignatureData(int methodID, int[] basicBlockOffsets)
  {
    int temp1 = basicBlockOffsets.length;
    long temp2 = 16661L * m_classSignature + (methodID + 1) * temp1;
    for (int i = 1; i < temp1; i++) {
      temp2 = 16661L * temp2 + basicBlockOffsets[i];
    }
    m_classSignature = temp2;
  }
  
  private static int lowbound(int[] values, int x)
  {
    int low = 0;int high = values.length - 1;
    while (low <= high)
    {
      int m = low + high >> 1;
      int v = values[m];
      if (v == x) {
        return m;
      }
      if (v < x) {
        low = m + 1;
      } else {
        high = m - 1;
      }
    }
    return high;
  }
  
  private void reset()
  {
    m_instrument = false;
    m_metadata = false;
    m_ignoreAlreadyInstrumented = false;
    
    m_cls = null;
    m_classPackageName = null;
    m_className = null;
    m_classSrcFileName = null;
    m_classBlockMetadata = ((int[][][])null);
    m_classMethodDescriptors = null;
    
    m_syntheticStringIndex = -1;
    m_coverageFieldrefIndex = -1;
    m_registerMethodrefIndex = -1;
    m_preclinitMethodrefIndex = -1;
    m_classNameConstantIndex = -1;
    m_clinitID = -1;
    m_clinitStatus = 0;
    m_classInstrMethodCount = -1;
    m_classBlockCounts = null;
    m_classSignature = 0L;
    
    m_methodID = -1;
    m_methodName = null;
    m_methodFirstLine = 0;
    m_methodBlockOffsets = null;
    m_methodJumpAdjOffsets = null;
    m_methodJumpAdjValues = null;
  }
  
  private static final LineNumberComparator LINE_NUMBER_COMPARATOR = new LineNumberComparator(null);
  private static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
}

/* Location:
 * Qualified Name:     com.vladium.emma.instr.InstrVisitor
 * Java Class Version: 1.2 (46.0)
 * JD-Core Version:    0.7.1
 */
package com.vladium.emma.instr;

import com.vladium.emma.Command;
import com.vladium.emma.EMMARuntimeException;
import com.vladium.util.ClassLoaderResolver;
import com.vladium.util.args.IOptsParser;
import com.vladium.util.args.IOptsParser.IOpt;
import com.vladium.util.args.IOptsParser.IOpts;
import com.vladium.util.asserts..assert;
import java.io.IOException;

public final class instrCommand
  extends Command
{
  private String[] m_instrpath;
  private String[] m_ixpath;
  private String m_outDirName;
  private String m_outFileName;
  private Boolean m_outDataMerge;
  private InstrProcessor.OutMode m_outMode;
  
  public instrCommand(String usageToolName, String[] args)
  {
    super(usageToolName, args);
    
    m_outMode = InstrProcessor.OutMode.OUT_MODE_COPY;
  }
  
  public synchronized void run()
  {
    ClassLoader loader;
    try
    {
      loader = ClassLoaderResolver.getClassLoader();
    }
    catch (Throwable t)
    {
      ClassLoader loader;
      loader = getClass().getClassLoader();
    }
    try
    {
      IOptsParser parser = getOptParser(loader);
      IOptsParser.IOpts parsedopts = parser.parse(m_args);
      
      int usageRequestLevel = parsedopts.usageRequestLevel();
      if (usageRequestLevel > 0)
      {
        usageexit(parser, usageRequestLevel, null);
        return;
      }
      IOptsParser.IOpt[] opts = parsedopts.getOpts();
      if (opts == null)
      {
        parsedopts.error(m_out, 80);
        usageexit(parser, 1, null);
        return;
      }
      try
      {
        for (int o = 0; o < opts.length; o++)
        {
          IOptsParser.IOpt opt = opts[o];
          String on = opt.getCanonicalName();
          if (!processOpt(opt)) {
            if ("ip".equals(on))
            {
              m_instrpath = getListOptValue(opt, PATH_DELIMITERS, true);
            }
            else if ("d".equals(on))
            {
              m_outDirName = opt.getFirstValue();
            }
            else if ("out".equals(on))
            {
              m_outFileName = opt.getFirstValue();
            }
            else if ("merge".equals(on))
            {
              m_outDataMerge = (getOptionalBooleanOptValue(opt) ? Boolean.TRUE : Boolean.FALSE);
            }
            else if ("ix".equals(on))
            {
              m_ixpath = getListOptValue(opt, ", \t\r\n", true);
            }
            else if ("m".equals(on))
            {
              String ov = opt.getFirstValue();
              
              InstrProcessor.OutMode outMode = InstrProcessor.OutMode.nameToMode(ov);
              if (outMode == null)
              {
                usageexit(parser, 1, "invalid '" + opts[o].getName() + "' option value: " + ov);
                
                return;
              }
              m_outMode = outMode;
            }
          }
        }
        if (!processFilePropertyOverrides()) {
          return;
        }
        processCmdPropertyOverrides(parsedopts);
      }
      catch (IOException ioe)
      {
        throw new EMMARuntimeException("ARGS_IO_FAILURE", ioe);
      }
      if ((m_outMode != InstrProcessor.OutMode.OUT_MODE_OVERWRITE) && (m_outDirName == null))
      {
        usageexit(parser, 1, "output directory must be specified for '" + m_outMode + "' output mode");
        
        return;
      }
      InstrProcessor processor = InstrProcessor.create();
      processor.setAppName("EMMA");
      
      processor.setInstrPath(m_instrpath, true);
      processor.setInclExclFilter(m_ixpath);
      .assert.ASSERT(m_outMode != null, "m_outMode not set");
      processor.setOutMode(m_outMode);
      processor.setInstrOutDir(m_outDirName);
      processor.setMetaOutFile(m_outFileName);
      processor.setMetaOutMerge(m_outDataMerge);
      processor.setPropertyOverrides(m_propertyOverrides);
      
      processor.run();
    }
    catch (EMMARuntimeException yre)
    {
      exit(true, yre.getMessage(), yre, 2);
      return;
    }
    catch (Throwable t)
    {
      exit(true, "unexpected failure: ", t, 2);
      return;
    }
    exit(false, null, null, 0);
  }
  
  protected void initialize()
  {
    super.initialize();
  }
  
  protected String usageArgsMsg()
  {
    return "[options]";
  }
}

/* Location:
 * Qualified Name:     com.vladium.emma.instr.instrCommand
 * Java Class Version: 1.2 (46.0)
 * JD-Core Version:    0.7.1
 */
package com.vladium.emma.report;

public abstract class AbstractItemVisitor
  implements IItemVisitor
{
  public Object visit(AllItem item, Object ctx)
  {
    return ctx;
  }
  
  public Object visit(PackageItem item, Object ctx)
  {
    return ctx;
  }
  
  public Object visit(SrcFileItem item, Object ctx)
  {
    return ctx;
  }
  
  public Object visit(ClassItem item, Object ctx)
  {
    return ctx;
  }
  
  public Object visit(MethodItem item, Object ctx)
  {
    return ctx;
  }
}

/* Location:
 * Qualified Name:     com.vladium.emma.report.AbstractItemVisitor
 * Java Class Version: 1.2 (46.0)
 * JD-Core Version:    0.7.1
 */
package com.vladium.emma.report;

import com.vladium.emma.EMMARuntimeException;
import com.vladium.emma.data.ClassDescriptor;
import com.vladium.emma.data.ICoverageData;
import com.vladium.emma.data.IMetaData;
import com.vladium.logging.Logger;
import com.vladium.util.Descriptors;
import com.vladium.util.IProperties;
import com.vladium.util.IntIntMap;
import com.vladium.util.IntVector;
import com.vladium.util.ObjectIntMap;
import java.util.Iterator;
import java.util.Set;
import java.util.TreeSet;

public abstract class AbstractReportGenerator
  extends AbstractItemVisitor
  implements IReportGenerator
{
  protected ReportProperties.ParsedProperties m_settings;
  protected SourcePathCache m_cache;
  protected IReportDataView m_view;
  protected boolean m_srcView;
  protected boolean m_hasSrcFileInfo;
  protected boolean m_hasLineNumberInfo;
  protected ItemComparator[] m_typeSortComparators;
  protected int[] m_metrics;
  protected Logger m_log;
  protected boolean m_verbose;
  private static final int MAX_DEBUG_INFO_WARNING_COUNT = 3;
  
  public static IReportGenerator create(String type)
  {
    if ((type == null) || (type.length() == 0)) {
      throw new IllegalArgumentException("null/empty input: type");
    }
    if ("html".equals(type)) {
      return new com.vladium.emma.report.html.ReportGenerator();
    }
    if ("txt".equals(type)) {
      return new com.vladium.emma.report.txt.ReportGenerator();
    }
    if ("xml".equals(type)) {
      return new com.vladium.emma.report.xml.ReportGenerator();
    }
    throw new EMMARuntimeException("no report generator class found for type [" + type + "]");
  }
  
  public void initialize(IMetaData mdata, ICoverageData cdata, SourcePathCache cache, IProperties properties)
    throws EMMARuntimeException
  {
    m_log = Logger.getLogger();
    m_verbose = m_log.atVERBOSE();
    
    m_settings = ReportProperties.parseProperties(properties, getType());
    
    m_cache = cache;
    
    m_hasSrcFileInfo = mdata.hasSrcFileData();
    m_hasLineNumberInfo = mdata.hasLineNumberData();
    
    boolean debugInfoWarning = false;
    boolean bailOut = false;
    if ((!mdata.hasSrcFileData()) && (m_settings.getViewType() == 1))
    {
      debugInfoWarning = true;
      
      m_log.warning("not all instrumented classes were compiled with source file");
      m_log.warning("debug data: no sources will be embedded in the report.");
      
      m_settings.setViewType(0);
    }
    if (!m_hasLineNumberInfo)
    {
      int[] userColumnIDs = m_settings.getColumnOrder();
      IntVector columnIDs = new IntVector();
      
      boolean removed = false;
      for (int c = 0; c < userColumnIDs.length; c++) {
        if (userColumnIDs[c] == 4) {
          removed = true;
        } else {
          columnIDs.add(userColumnIDs[c]);
        }
      }
      if (removed)
      {
        debugInfoWarning = true;
        if (columnIDs.size() == 0)
        {
          m_log.warning("line coverage requested in a report of type [" + getType() + "] but");
          m_log.warning("not all instrumented classes were compiled with line number");
          m_log.warning("debug data: since this was the only requested column, no report will be generated.");
          
          bailOut = true;
        }
        else
        {
          m_log.warning("line coverage requested in a report of type [" + getType() + "] but");
          m_log.warning("not all instrumented classes were compiled with line number");
          m_log.warning("debug data: this column will be removed from the report.");
          
          m_settings.setColumnOrder(columnIDs.values());
          
          int[] userSort = m_settings.getSortOrder();
          IntVector sort = new IntVector();
          for (int c = 0; c < userSort.length; c += 2) {
            if (Math.abs(userSort[c]) != 4)
            {
              sort.add(userSort[c]);
              sort.add(userSort[(c + 1)]);
            }
          }
          m_settings.setSortOrder(sort.values());
        }
      }
    }
    Iterator names;
    if ((debugInfoWarning) && (m_log.atINFO()))
    {
      Set sampleClassNames = new TreeSet();
      ObjectIntMap countMap = new ObjectIntMap();
      int[] _count = new int[1];
      for (Iterator descriptors = mdata.iterator(); descriptors.hasNext();)
      {
        ClassDescriptor cls = (ClassDescriptor)descriptors.next();
        if ((!cls.hasCompleteLineNumberInfo()) || (!cls.hasSrcFileInfo()))
        {
          String packageVMName = cls.getPackageVMName();
          int count = countMap.get(packageVMName, _count) ? _count[0] : 0;
          if (count < 3)
          {
            sampleClassNames.add(Descriptors.vmNameToJavaName(cls.getClassVMName()));
            countMap.put(packageVMName, count + 1);
          }
        }
      }
      m_log.info("showing up to 3 classes without full debug info per package:");
      for (names = sampleClassNames.iterator(); names.hasNext();) {
        m_log.info("  " + names.next());
      }
    }
    if (bailOut) {
      throw new EMMARuntimeException("BAILED OUT");
    }
    IItemMetadata[] allTypes = IItemMetadata.Factory.getAllTypes();
    m_typeSortComparators = new ItemComparator[allTypes.length];
    for (int t = 0; t < allTypes.length; t++)
    {
      IntVector orderedAttrIDsWithDir = new IntVector();
      long typeAttrIDSet = allTypes[t].getAttributeIDs();
      for (int s = 0; s < m_settings.getSortOrder().length; s += 2)
      {
        int attrID = m_settings.getSortOrder()[s];
        if ((typeAttrIDSet & 1 << attrID) != 0L)
        {
          orderedAttrIDsWithDir.add(attrID);
          
          int dir = m_settings.getSortOrder()[(s + 1)];
          orderedAttrIDsWithDir.add(dir);
        }
      }
      m_typeSortComparators[t] = ItemComparator.Factory.create(orderedAttrIDsWithDir.values(), m_settings.getUnitsType());
    }
    m_metrics = new int[allTypes.length];
    IntIntMap metrics = m_settings.getMetrics();
    for (int t = 0; t < m_metrics.length; t++)
    {
      m_metrics[t] = -1;
      metrics.get(t, m_metrics, t);
    }
    IReportDataModel model = IReportDataModel.Factory.create(mdata, cdata);
    m_view = model.getView(m_settings.getViewType());
    
    m_srcView = (m_settings.getViewType() == 1);
  }
  
  public void cleanup()
  {
    reset();
  }
  
  protected void reset()
  {
    m_settings = null;
    m_cache = null;
    m_view = null;
    m_srcView = false;
    
    m_typeSortComparators = null;
    m_metrics = null;
    
    m_log = null;
  }
}

/* Location:
 * Qualified Name:     com.vladium.emma.report.AbstractReportGenerator
 * Java Class Version: 1.2 (46.0)
 * JD-Core Version:    0.7.1
 */
package com.vladium.emma.report;

public final class AllItem
  extends Item
{
  public AllItem()
  {
    super(null);
  }
  
  public String getName()
  {
    return "all classes";
  }
  
  public void accept(IItemVisitor visitor, Object ctx)
  {
    visitor.visit(this, ctx);
  }
  
  public final IItemMetadata getMetadata()
  {
    return METADATA;
  }
  
  public static IItemMetadata getTypeMetadata()
  {
    return METADATA;
  }
  
  private static final Item.ItemMetadata METADATA = new Item.ItemMetadata(0, "all", 31L);
}

/* Location:
 * Qualified Name:     com.vladium.emma.report.AllItem
 * Java Class Version: 1.2 (46.0)
 * JD-Core Version:    0.7.1
 */
package com.vladium.emma.report;

import com.vladium.emma.data.ClassDescriptor;
import com.vladium.emma.data.MethodDescriptor;
import com.vladium.util.IntObjectMap;
import java.util.Iterator;

public final class ClassItem
  extends Item
{
  final ClassDescriptor m_cls;
  final boolean[][] m_coverage;
  private int m_firstLine;
  
  public ClassItem(IItem parent, ClassDescriptor cls, boolean[][] coverage)
  {
    super(parent);
    
    m_cls = cls;
    m_coverage = coverage;
  }
  
  public String getName()
  {
    return m_cls.getName();
  }
  
  public String getSrcFileName()
  {
    return m_cls.getSrcFileName();
  }
  
  public int getFirstLine()
  {
    if (m_firstLine == 0)
    {
      MethodDescriptor[] methods = m_cls.getMethods();
      
      int firstLine = Integer.MAX_VALUE;
      int m = 0;
      for (int mLimit = methods.length; m < mLimit; m++)
      {
        int mFirstLine = methods[m].getFirstLine();
        if ((mFirstLine > 0) && (mFirstLine < firstLine)) {
          firstLine = mFirstLine;
        }
      }
      m_firstLine = firstLine;
      return firstLine;
    }
    return m_firstLine;
  }
  
  public ClassDescriptor getClassDescriptor()
  {
    return m_cls;
  }
  
  public boolean[][] getCoverage()
  {
    return m_coverage;
  }
  
  public boolean loaded()
  {
    return m_coverage != null;
  }
  
  public int getAggregate(int type)
  {
    int[] aggregates = m_aggregates;
    
    int value = aggregates[type];
    if (value < 0)
    {
      switch (type)
      {
      case 5: 
      case 11: 
        aggregates[11] = 1;
        aggregates[5] = (m_coverage != null ? 1 : 0);
        
        return aggregates[type];
      case 1: 
      case 3: 
      case 7: 
        boolean[][] ccoverage = m_coverage;
        
        IntObjectMap cldata = new IntObjectMap();
        MethodDescriptor[] methoddescs = m_cls.getMethods();
        for (Iterator methods = getChildren(); methods.hasNext();)
        {
          MethodItem method = (MethodItem)methods.next();
          int methodID = method.getID();
          
          boolean[] mcoverage = ccoverage == null ? null : ccoverage[methodID];
          
          MethodDescriptor methoddesc = methoddescs[methodID];
          int[] mbsizes = methoddesc.getBlockSizes();
          IntObjectMap mlineMap = methoddesc.getLineMap();
          
          int[] mlines = mlineMap.keys();
          int ml = 0;
          for (int mlLimit = mlines.length; ml < mlLimit; ml++)
          {
            int mline = mlines[ml];
            
            int[] data = (int[])cldata.get(mline);
            if (data == null)
            {
              data = new int[4];
              cldata.put(mline, data);
            }
            int[] lblocks = (int[])mlineMap.get(mline);
            
            int bCount = lblocks.length;
            data[0] += bCount;
            for (int bID = 0; bID < bCount; bID++)
            {
              int block = lblocks[bID];
              
              boolean bcovered = (mcoverage != null) && (mcoverage[block] != 0);
              int instr = 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22

Further reading...

For more information on Java 1.5 Tiger, you may find Java 1.5 Tiger, A developer's Notebook by D. Flanagan and B. McLaughlin from O'Reilly of interest.

New!JAR listings


Copyright 2006-2017. Infinite Loop Ltd