예제 #1
0
  protected final void atReturnStmnt2(ASTree result) throws CompileError {
    int op;
    if (result == null) op = Opcode.RETURN;
    else {
      compileExpr(result);
      if (arrayDim > 0) op = ARETURN;
      else {
        int type = exprType;
        if (type == DOUBLE) op = DRETURN;
        else if (type == FLOAT) op = FRETURN;
        else if (type == LONG) op = LRETURN;
        else if (isRefType(type)) op = ARETURN;
        else op = IRETURN;
      }
    }

    for (ReturnHook har = returnHooks; har != null; har = har.next)
      if (har.doit(bytecode, op)) {
        hasReturned = true;
        return;
      }

    bytecode.addOpcode(op);
    hasReturned = true;
  }
예제 #2
0
  private void atThrowStmnt(Stmnt st) throws CompileError {
    ASTree e = st.getLeft();
    compileExpr(e);
    if (exprType != CLASS || arrayDim > 0) throw new CompileError("bad throw statement");

    bytecode.addOpcode(ATHROW);
    hasReturned = true;
  }
예제 #3
0
  private void atSwitchStmnt(Stmnt st) throws CompileError {
    compileExpr(st.head());

    ArrayList prevBreakList = breakList;
    breakList = new ArrayList();
    int opcodePc = bytecode.currentPc();
    bytecode.addOpcode(LOOKUPSWITCH);
    int npads = 3 - (opcodePc & 3);
    while (npads-- > 0) bytecode.add(0);

    Stmnt body = (Stmnt) st.tail();
    int npairs = 0;
    for (ASTList list = body; list != null; list = list.tail())
      if (((Stmnt) list.head()).getOperator() == CASE) ++npairs;

    // opcodePc2 is the position at which the default jump offset is.
    int opcodePc2 = bytecode.currentPc();
    bytecode.addGap(4);
    bytecode.add32bit(npairs);
    bytecode.addGap(npairs * 8);

    long[] pairs = new long[npairs];
    int ipairs = 0;
    int defaultPc = -1;
    for (ASTList list = body; list != null; list = list.tail()) {
      Stmnt label = (Stmnt) list.head();
      int op = label.getOperator();
      if (op == DEFAULT) defaultPc = bytecode.currentPc();
      else if (op != CASE) fatal();
      else {
        pairs[ipairs++] =
            ((long) computeLabel(label.head()) << 32)
                + ((long) (bytecode.currentPc() - opcodePc) & 0xffffffff);
      }

      hasReturned = false;
      ((Stmnt) label.tail()).accept(this);
    }

    Arrays.sort(pairs);
    int pc = opcodePc2 + 8;
    for (int i = 0; i < npairs; ++i) {
      bytecode.write32bit(pc, (int) (pairs[i] >>> 32));
      bytecode.write32bit(pc + 4, (int) pairs[i]);
      pc += 8;
    }

    if (defaultPc < 0 || breakList.size() > 0) hasReturned = false;

    int endPc = bytecode.currentPc();
    if (defaultPc < 0) defaultPc = endPc;

    bytecode.write32bit(opcodePc2, defaultPc - opcodePc);

    patchGoto(breakList, endPc);
    breakList = prevBreakList;
  }
예제 #4
0
  private void atSyncStmnt(Stmnt st) throws CompileError {
    int nbreaks = getListSize(breakList);
    int ncontinues = getListSize(continueList);

    compileExpr(st.head());
    if (exprType != CLASS && arrayDim == 0)
      throw new CompileError("bad type expr for synchronized block");

    Bytecode bc = bytecode;
    final int var = bc.getMaxLocals();
    bc.incMaxLocals(1);
    bc.addOpcode(DUP);
    bc.addAstore(var);
    bc.addOpcode(MONITORENTER);

    ReturnHook rh =
        new ReturnHook(this) {
          protected boolean doit(Bytecode b, int opcode) {
            b.addAload(var);
            b.addOpcode(MONITOREXIT);
            return false;
          }
        };

    int pc = bc.currentPc();
    Stmnt body = (Stmnt) st.tail();
    if (body != null) body.accept(this);

    int pc2 = bc.currentPc();
    int pc3 = 0;
    if (!hasReturned) {
      rh.doit(bc, 0); // the 2nd arg is ignored.
      bc.addOpcode(Opcode.GOTO);
      pc3 = bc.currentPc();
      bc.addIndex(0);
    }

    if (pc < pc2) { // if the body is not empty
      int pc4 = bc.currentPc();
      rh.doit(bc, 0); // the 2nd arg is ignored.
      bc.addOpcode(ATHROW);
      bc.addExceptionHandler(pc, pc2, pc4, 0);
    }

    if (!hasReturned) bc.write16bit(pc3, bc.currentPc() - pc3 + 1);

    rh.remove(this);

    if (getListSize(breakList) != nbreaks || getListSize(continueList) != ncontinues)
      throw new CompileError("sorry, cannot break/continue in synchronized block");
  }