Example #1
0
  /** Generate code */
  public void write(Environment env, DataOutputStream out, MemberDefinition field, ConstantPool tab)
      throws IOException {
    // listing(System.out);

    if ((field != null) && field.getArguments() != null) {
      int sum = 0;
      Vector v = field.getArguments();
      for (Enumeration e = v.elements(); e.hasMoreElements(); ) {
        MemberDefinition f = ((MemberDefinition) e.nextElement());
        sum += f.getType().stackSize();
      }
      maxvar = sum;
    }

    // Make sure the stack balances.  Also calculate maxvar and maxstack
    try {
      balance(first, 0);
    } catch (CompilerError e) {
      System.out.println("ERROR: " + e);
      listing(System.out);
      throw e;
    }

    // Assign PCs
    int pc = 0, nexceptions = 0;
    for (Instruction inst = first; inst != null; inst = inst.next) {
      inst.pc = pc;
      int sz = inst.size(tab);
      if (pc < 65536 && (pc + sz) >= 65536) {
        env.error(inst.where, "warn.method.too.long");
      }
      pc += sz;

      if (inst.opc == opc_try) {
        nexceptions += ((TryData) inst.value).catches.size();
      }
    }

    // Write header
    out.writeShort(maxdepth);
    out.writeShort(maxvar);
    out.writeInt(maxpc = pc);

    // Generate code
    for (Instruction inst = first.next; inst != null; inst = inst.next) {
      inst.write(out, tab);
    }

    // write exceptions
    out.writeShort(nexceptions);
    if (nexceptions > 0) {
      // listing(System.out);
      writeExceptions(env, out, tab, first, last);
    }
  }
Example #2
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;
          }
      }
    }
  }