public String toString() {
            return "member(" + member + (nonvirtual ? " nonvirtual)" : ")");
        }
    }

    /** An item representing a literal.
     */
    class ImmediateItem extends Item {

        /** The literal's value.
         */
        Object value;

        ImmediateItem(Type type, Object value) {
            super(Code.typecode(type));
            this.value = value;
        }

        private void ldc() {
            int idx = pool.put(value);
            if (typecode == LONGcode || typecode == DOUBLEcode) {
                code.emitop2(ldc2w, idx);
            } else if (idx <= 255) {
                code.emitop1(ldc1, idx);
            } else {
                code.emitop2(ldc2, idx);
            }
        }

        Item load() {
            switch (typecode) {
            case INTcode: case BYTEcode: case SHORTcode: case CHARcode:
                int ival = ((Number)value).intValue();
                if (-1 <= ival && ival <= 5)
                    code.emitop0(iconst_0 + ival);
                else if (Byte.MIN_VALUE <= ival && ival <= Byte.MAX_VALUE)
                    code.emitop1(bipush, ival);
                else if (Short.MIN_VALUE <= ival && ival <= Short.MAX_VALUE)
                    code.emitop2(sipush, ival);
                else
                    ldc();
                break;
            case LONGcode:
                long lval = ((Number)value).longValue();
                if (lval == 0 || lval == 1)
                    code.emitop0(lconst_0 + (int)lval);
                else
                    ldc();
                break;
            case FLOATcode:
                float fval = ((Number)value).floatValue();
                if (isPosZero(fval) || fval == 1.0 || fval == 2.0)
                    code.emitop0(fconst_0 + (int)fval);
                else {
                    ldc();
                }
                break;
            case DOUBLEcode:
                double dval = ((Number)value).doubleValue();
                if (isPosZero(dval) || dval == 1.0)
                    code.emitop0(dconst_0 + (int)dval);
                else
                    ldc();
                break;
            case OBJECTcode:
                ldc();
                break;
            default:
                Assert.error();
            }
            return stackItem[typecode];
        }
        //where
            /** Return true iff float number is positive 0.
             */
            private boolean isPosZero(float x) {
                return x == 0.0f && 1.0f / x > 0.0f;
            }
            /** Return true iff double number is positive 0.
             */
            private boolean isPosZero(double x) {
                return x == 0.0d && 1.0d / x > 0.0d;
            }

        CondItem mkCond() {
            int ival = ((Number)value).intValue();
            return makeCondItem(ival != 0 ? goto_ : dontgoto);
        }

        Item coerce(int targetcode) {
            if (typecode == targetcode) {
                return this;
            } else {
                switch (targetcode) {
                case INTcode:
                    if (Code.truncate(typecode) == INTcode)
                        return this;
                    else
                        return new ImmediateItem(
                            syms.intType,
                            ((Number)value).intValue());
                case LONGcode:
                    return new ImmediateItem(
                        syms.longType,
                        ((Number)value).longValue());
                case FLOATcode:
                    return new ImmediateItem(
                        syms.floatType,
                        ((Number)value).floatValue());
                case DOUBLEcode:
                    return new ImmediateItem(
                        syms.doubleType,
                        ((Number)value).doubleValue());
                case BYTEcode:
                    return new ImmediateItem(
                        syms.byteType,
                        (int)(byte)((Number)value).intValue());
                case CHARcode:
                    return new ImmediateItem(
                        syms.charType,
                        (int)(char)((Number)value).intValue());
                case SHORTcode:
                    return new ImmediateItem(
                        syms.shortType,
                        (int)(short)((Number)value).intValue());
                default:
                    return super.coerce(targetcode);
                }
            }
        }

        public String toString() {
            return "immediate(" + value + ")";
        }
    }

    /** An item representing an assignment expressions.
     */
    class AssignItem extends Item {

        /** The item representing the assignment's left hand side.
         */
        Item lhs;

        AssignItem(Item lhs) {
            super(lhs.typecode);
            this.lhs = lhs;
        }

        Item load() {
            lhs.stash(typecode);
            lhs.store();
            return stackItem[typecode];
        }

        void duplicate() {
            load().duplicate();
        }

        void drop() {
            lhs.store();
        }

        void stash(int toscode) {
            Assert.error();
        }

        int width() {
            return lhs.width() + Code.width(typecode);
        }

        public String toString() {
            return "assign(lhs = " + lhs + ")";
        }
    }

    /** An item representing a conditional or unconditional jump.
     */
    class CondItem extends Item {

        /** A chain encomassing all jumps that can be taken
         *  if the condition evaluates to true.
         */
        Chain trueJumps;

        /** A chain encomassing all jumps that can be taken
         *  if the condition evaluates to false.
         */
        Chain falseJumps;

        /** The jump's opcode.
         */
        int opcode;

        /*
         *  An abstract syntax tree of this item. It is needed
         *  for branch entries in 'CharacterRangeTable' attribute.
         */
        JCTree tree;

        CondItem(int opcode, Chain truejumps, Chain falsejumps) {
            super(BYTEcode);
            this.opcode = opcode;
            this.trueJumps = truejumps;
            this.falseJumps = falsejumps;
        }

        Item load() {
            Chain trueChain = null;
            Chain falseChain = jumpFalse();
            if (!isFalse()) {
                code.resolve(trueJumps);
                code.emitop0(iconst_1);
                trueChain = code.branch(goto_);
            }
            if (falseChain != null) {
                code.resolve(falseChain);
                code.emitop0(iconst_0);
            }
            code.resolve(trueChain);
            return stackItem[typecode];
        }

        void duplicate() {
            load().duplicate();
        }

        void drop() {
            load().drop();
        }

        void stash(int toscode) {
            Assert.error();
        }

        CondItem mkCond() {
            return this;
        }

        Chain jumpTrue() {
            if (tree == null) return Code.mergeChains(trueJumps, code.branch(opcode));
            // we should proceed further in -Xjcov mode only
            int startpc = code.curPc();
            Chain c = Code.mergeChains(trueJumps, code.branch(opcode));
            code.crt.put(tree, CRTable.CRT_BRANCH_TRUE, startpc, code.curPc());
            return c;
        }

        Chain jumpFalse() {
            if (tree == null) return Code.mergeChains(falseJumps, code.branch(Code.negate(opcode)));
            // we should proceed further in -Xjcov mode only
            int startpc = code.curPc();
            Chain c = Code.mergeChains(falseJumps, code.branch(Code.negate(opcode)));
            code.crt.put(tree, CRTable.CRT_BRANCH_FALSE, startpc, code.curPc());
            return c;
        }

        CondItem negate() {
            CondItem c = new CondItem(Code.negate(opcode), falseJumps, trueJumps);
            c.tree = tree;
            return c;
        }

        int width() {
            // a CondItem doesn't have a size on the stack per se.
            throw new AssertionError();
        }

        boolean isTrue() {
            return falseJumps == null && opcode == goto_;
        }

        boolean isFalse() {
            return trueJumps == null && opcode == dontgoto;
        }

        public String toString() {
            return "cond(" + Code.mnem(opcode) + ")";
        }