Example #1
0
 /** Write the exceptions table */
 void writeExceptions(
     Environment env, DataOutputStream out, ConstantPool tab, Instruction first, Instruction last)
     throws IOException {
   for (Instruction inst = first; inst != last.next; inst = inst.next) {
     if (inst.opc == opc_try) {
       TryData td = (TryData) inst.value;
       writeExceptions(env, out, tab, inst.next, td.getEndLabel());
       for (Enumeration e = td.catches.elements(); e.hasMoreElements(); ) {
         CatchData cd = (CatchData) e.nextElement();
         // System.out.println("EXCEPTION: " + env.getSource() + ", pc=" + inst.pc + ", end=" +
         // td.getEndLabel().pc + ", hdl=" + cd.getLabel().pc + ", tp=" + cd.getType());
         out.writeShort(inst.pc);
         out.writeShort(td.getEndLabel().pc);
         out.writeShort(cd.getLabel().pc);
         if (cd.getType() != null) {
           out.writeShort(tab.index(cd.getType()));
         } else {
           out.writeShort(0);
         }
       }
       inst = td.getEndLabel();
     }
   }
 }
Example #2
0
  /** Optimize instructions and mark those that can be reached */
  void optimize(Environment env, Label lbl) {
    lbl.pc = REACHED;

    for (Instruction inst = lbl.next; inst != null; inst = inst.next) {
      switch (inst.pc) {
        case NOTREACHED:
          inst.optimize(env);
          inst.pc = REACHED;
          break;
        case REACHED:
          return;
        case NEEDED:
          break;
      }

      switch (inst.opc) {
        case opc_label:
        case opc_dead:
          if (inst.pc == REACHED) {
            inst.pc = NOTREACHED;
          }
          break;

        case opc_ifeq:
        case opc_ifne:
        case opc_ifgt:
        case opc_ifge:
        case opc_iflt:
        case opc_ifle:
        case opc_if_icmpeq:
        case opc_if_icmpne:
        case opc_if_icmpgt:
        case opc_if_icmpge:
        case opc_if_icmplt:
        case opc_if_icmple:
        case opc_if_acmpeq:
        case opc_if_acmpne:
        case opc_ifnull:
        case opc_ifnonnull:
          optimize(env, (Label) inst.value);
          break;

        case opc_goto:
          optimize(env, (Label) inst.value);
          return;

        case opc_jsr:
          optimize(env, (Label) inst.value);
          break;

        case opc_ret:
        case opc_return:
        case opc_ireturn:
        case opc_lreturn:
        case opc_freturn:
        case opc_dreturn:
        case opc_areturn:
        case opc_athrow:
          return;

        case opc_tableswitch:
        case opc_lookupswitch:
          {
            SwitchData sw = (SwitchData) inst.value;
            optimize(env, sw.defaultLabel);
            for (Enumeration e = sw.tab.elements(); e.hasMoreElements(); ) {
              optimize(env, (Label) e.nextElement());
            }
            return;
          }

        case opc_try:
          {
            TryData td = (TryData) inst.value;
            td.getEndLabel().pc = NEEDED;
            for (Enumeration e = td.catches.elements(); e.hasMoreElements(); ) {
              CatchData cd = (CatchData) e.nextElement();
              optimize(env, cd.getLabel());
            }
            break;
          }
      }
    }
  }
Example #3
0
  /**
   * Figure out when registers contain a legal value. This is done using a simple data flow
   * algorithm. This information is later used to generate the local variable table.
   */
  void flowFields(Environment env, Label lbl, MemberDefinition locals[]) {
    if (lbl.locals != null) {
      // Been here before. Erase any conflicts.
      MemberDefinition f[] = lbl.locals;
      for (int i = 0; i < maxvar; i++) {
        if (f[i] != locals[i]) {
          f[i] = null;
        }
      }
      return;
    }

    // Remember the set of active registers at this point
    lbl.locals = new MemberDefinition[maxvar];
    System.arraycopy(locals, 0, lbl.locals, 0, maxvar);

    MemberDefinition newlocals[] = new MemberDefinition[maxvar];
    System.arraycopy(locals, 0, newlocals, 0, maxvar);
    locals = newlocals;

    for (Instruction inst = lbl.next; inst != null; inst = inst.next) {
      switch (inst.opc) {
        case opc_istore:
        case opc_istore_0:
        case opc_istore_1:
        case opc_istore_2:
        case opc_istore_3:
        case opc_fstore:
        case opc_fstore_0:
        case opc_fstore_1:
        case opc_fstore_2:
        case opc_fstore_3:
        case opc_astore:
        case opc_astore_0:
        case opc_astore_1:
        case opc_astore_2:
        case opc_astore_3:
        case opc_lstore:
        case opc_lstore_0:
        case opc_lstore_1:
        case opc_lstore_2:
        case opc_lstore_3:
        case opc_dstore:
        case opc_dstore_0:
        case opc_dstore_1:
        case opc_dstore_2:
        case opc_dstore_3:
          if (inst.value instanceof LocalVariable) {
            LocalVariable v = (LocalVariable) inst.value;
            locals[v.slot] = v.field;
          }
          break;

        case opc_label:
          flowFields(env, (Label) inst, locals);
          return;

        case opc_ifeq:
        case opc_ifne:
        case opc_ifgt:
        case opc_ifge:
        case opc_iflt:
        case opc_ifle:
        case opc_if_icmpeq:
        case opc_if_icmpne:
        case opc_if_icmpgt:
        case opc_if_icmpge:
        case opc_if_icmplt:
        case opc_if_icmple:
        case opc_if_acmpeq:
        case opc_if_acmpne:
        case opc_ifnull:
        case opc_ifnonnull:
        case opc_jsr:
          flowFields(env, (Label) inst.value, locals);
          break;

        case opc_goto:
          flowFields(env, (Label) inst.value, locals);
          return;

        case opc_return:
        case opc_ireturn:
        case opc_lreturn:
        case opc_freturn:
        case opc_dreturn:
        case opc_areturn:
        case opc_athrow:
        case opc_ret:
          return;

        case opc_tableswitch:
        case opc_lookupswitch:
          {
            SwitchData sw = (SwitchData) inst.value;
            flowFields(env, sw.defaultLabel, locals);
            for (Enumeration e = sw.tab.elements(); e.hasMoreElements(); ) {
              flowFields(env, (Label) e.nextElement(), locals);
            }
            return;
          }

        case opc_try:
          {
            Vector catches = ((TryData) inst.value).catches;
            for (Enumeration e = catches.elements(); e.hasMoreElements(); ) {
              CatchData cd = (CatchData) e.nextElement();
              flowFields(env, cd.getLabel(), locals);
            }
            break;
          }
      }
    }
  }
Example #4
0
  /** Determine stack size, count local variables */
  void balance(Label lbl, int depth) {
    for (Instruction inst = lbl; inst != null; inst = inst.next) {
      // Environment.debugOutput(inst.toString() + ": " + depth + " => " +
      //                                 (depth + inst.balance()));
      depth += inst.balance();
      if (depth < 0) {
        throw new CompilerError("stack under flow: " + inst.toString() + " = " + depth);
      }
      if (depth > maxdepth) {
        maxdepth = depth;
      }
      switch (inst.opc) {
        case opc_label:
          lbl = (Label) inst;
          if (inst.pc == REACHED) {
            if (lbl.depth != depth) {
              throw new CompilerError(
                  "stack depth error " + depth + "/" + lbl.depth + ": " + inst.toString());
            }
            return;
          }
          lbl.pc = REACHED;
          lbl.depth = depth;
          break;

        case opc_ifeq:
        case opc_ifne:
        case opc_ifgt:
        case opc_ifge:
        case opc_iflt:
        case opc_ifle:
        case opc_if_icmpeq:
        case opc_if_icmpne:
        case opc_if_icmpgt:
        case opc_if_icmpge:
        case opc_if_icmplt:
        case opc_if_icmple:
        case opc_if_acmpeq:
        case opc_if_acmpne:
        case opc_ifnull:
        case opc_ifnonnull:
          balance((Label) inst.value, depth);
          break;

        case opc_goto:
          balance((Label) inst.value, depth);
          return;

        case opc_jsr:
          balance((Label) inst.value, depth + 1);
          break;

        case opc_ret:
        case opc_return:
        case opc_ireturn:
        case opc_lreturn:
        case opc_freturn:
        case opc_dreturn:
        case opc_areturn:
        case opc_athrow:
          return;

        case opc_iload:
        case opc_fload:
        case opc_aload:
        case opc_istore:
        case opc_fstore:
        case opc_astore:
          {
            int v =
                ((inst.value instanceof Number)
                        ? ((Number) inst.value).intValue()
                        : ((LocalVariable) inst.value).slot)
                    + 1;
            if (v > maxvar) maxvar = v;
            break;
          }

        case opc_lload:
        case opc_dload:
        case opc_lstore:
        case opc_dstore:
          {
            int v =
                ((inst.value instanceof Number)
                        ? ((Number) inst.value).intValue()
                        : ((LocalVariable) inst.value).slot)
                    + 2;
            if (v > maxvar) maxvar = v;
            break;
          }

        case opc_iinc:
          {
            int v = ((int[]) inst.value)[0] + 1;
            if (v > maxvar) maxvar = v + 1;
            break;
          }

        case opc_tableswitch:
        case opc_lookupswitch:
          {
            SwitchData sw = (SwitchData) inst.value;
            balance(sw.defaultLabel, depth);
            for (Enumeration e = sw.tab.elements(); e.hasMoreElements(); ) {
              balance((Label) e.nextElement(), depth);
            }
            return;
          }

        case opc_try:
          {
            TryData td = (TryData) inst.value;
            for (Enumeration e = td.catches.elements(); e.hasMoreElements(); ) {
              CatchData cd = (CatchData) e.nextElement();
              balance(cd.getLabel(), depth + 1);
            }
            break;
          }
      }
    }
  }