/*
 * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package com.sun.tools.javac.jvm;

import com.sun.tools.javac.code.*;
import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.code.Type.*;
import com.sun.tools.javac.jvm.Code.*;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.util.Assert;

import static com.sun.tools.javac.jvm.ByteCodes.*;

/** A helper class for code generation. Items are objects
 *  that stand for addressable entities in the bytecode. Each item
 *  supports a fixed protocol for loading the item on the stack, storing
 *  into it, converting it into a jump condition, and several others.
 *  There are many individual forms of items, such as local, static,
 *  indexed, or instance variables, values on the top of stack, the
 *  special values this or super, etc. Individual items are represented as
 *  inner classes in class Items.
 *
 *  <p><b>This is NOT part of any supported API.
 *  If you write code that depends on this, you do so at your own risk.
 *  This code and its internal interfaces are subject to change or
 *  deletion without notice.</b>
 */
public class Items {

    /** The current constant pool.
     */
    Pool pool;

    /** The current code buffer.
     */
    Code code;

    /** The current symbol table.
     */
    Symtab syms;

    /** Type utilities. */
    Types types;

    /** Items that exist only once (flyweight pattern).
     */
    private final Item voidItem;
    private final Item thisItem;
    private final Item superItem;
    private final Item[] stackItem = new Item[TypeCodeCount];

    public Items(Pool pool, Code code, Symtab syms, Types types) {
        this.code = code;
        this.pool = pool;
        this.types = types;
        voidItem = new Item(VOIDcode) {
                public String toString() { return "void"; }
            };
        thisItem = new SelfItem(false);
        superItem = new SelfItem(true);
        for (int i = 0; i < VOIDcode; i++) stackItem[i] = new StackItem(i);
        stackItem[VOIDcode] = voidItem;
        this.syms = syms;
    }

    /** Make a void item
     */
    Item makeVoidItem() {
        return voidItem;
    }
    /** Make an item representing `this'.
     */
    Item makeThisItem() {
        return thisItem;
    }

    /** Make an item representing `super'.
     */
    Item makeSuperItem() {
        return superItem;
    }

    /** Make an item representing a value on stack.
     *  @param type    The value's type.
     */
    Item makeStackItem(Type type) {
        return stackItem[Code.typecode(type)];
    }

    /** Make an item representing a dynamically invoked method.
     *  @param member   The represented symbol.
     */
    Item makeDynamicItem(Symbol member) {
        return new DynamicItem(member);
    }

    /** Make an item representing an indexed expression.
     *  @param type    The expression's type.
     */
    Item makeIndexedItem(Type type) {
        return new IndexedItem(type);
    }

    /** Make an item representing a local variable.
     *  @param v    The represented variable.
     */
    LocalItem makeLocalItem(VarSymbol v) {
        return new LocalItem(v.erasure(types), v.adr);
    }

    /** Make an item representing a local anonymous variable.
     *  @param type  The represented variable's type.
     *  @param reg   The represented variable's register.
     */
    private LocalItem makeLocalItem(Type type, int reg) {
        return new LocalItem(type, reg);
    }

    /** Make an item representing a static variable or method.
     *  @param member   The represented symbol.
     */
    Item makeStaticItem(Symbol member) {
        return new StaticItem(member);
    }

    /** Make an item representing an instance variable or method.
     *  @param member       The represented symbol.
     *  @param nonvirtual   Is the reference not virtual? (true for constructors
     *                      and private members).
     */
    Item makeMemberItem(Symbol member, boolean nonvirtual) {
        return new MemberItem(member, nonvirtual);
    }

    /** Make an item representing a literal.
     *  @param type     The literal's type.
     *  @param value    The literal's value.
     */
    Item makeImmediateItem(Type type, Object value) {
        return new ImmediateItem(type, value);
    }

    /** Make an item representing an assignment expression.
     *  @param lhs      The item representing the assignment's left hand side.
     */
    Item makeAssignItem(Item lhs) {
        return new AssignItem(lhs);
    }

    /** Make an item representing a conditional or unconditional jump.
     *  @param opcode      The jump's opcode.
     *  @param trueJumps   A chain encomassing all jumps that can be taken
     *                     if the condition evaluates to true.
     *  @param falseJumps  A chain encomassing all jumps that can be taken
     *                     if the condition evaluates to false.
     */
    CondItem makeCondItem(int opcode, Chain trueJumps, Chain falseJumps) {
        return new CondItem(opcode, trueJumps, falseJumps);
    }

    /** Make an item representing a conditional or unconditional jump.
     *  @param opcode      The jump's opcode.
     */
    CondItem makeCondItem(int opcode) {
        return makeCondItem(opcode, null, null);
    }

    /** The base class of all items, which implements default behavior.
     */
    abstract class Item {

        /** The type code of values represented by this item.
         */
        int typecode;

        Item(int typecode) {
            this.typecode = typecode;
        }

        /** Generate code to load this item onto stack.
         */
        Item load() {
            throw new AssertionError();
        }

        /** Generate code to store top of stack into this item.
         */
        void store() {
            throw new AssertionError("store unsupported: " + this);
        }

        /** Generate code to invoke method represented by this item.
         */
        Item invoke() {
            throw new AssertionError(this);
        }

        /** Generate code to use this item twice.
         */
        void duplicate() {}

        /** Generate code to avoid having to use this item.
         */
        void drop() {}

        /** Generate code to stash a copy of top of stack - of typecode toscode -
         *  under this item.
         */
        void stash(int toscode) {
            stackItem[toscode].duplicate();
        }

        /** Generate code to turn item into a testable condition.
         */
        CondItem mkCond() {
            load();
            return makeCondItem(ifne);
        }

        /** Generate code to coerce item to given type code.
         *  @param targetcode    The type code to coerce to.
         */
        Item coerce(int targetcode) {
            if (typecode == targetcode)
                return this;
            else {
                load();
                int typecode1 = Code.truncate(typecode);
                int targetcode1 = Code.truncate(targetcode);
                if (typecode1 != targetcode1) {
                    int offset = targetcode1 > typecode1 ? targetcode1 - 1
                        : targetcode1;
                    code.emitop0(i2l + typecode1 * 3 + offset);
                }
                if (targetcode != targetcode1) {
                    code.emitop0(int2byte + targetcode - BYTEcode);
                }
                return stackItem[targetcode];
            }
        }

        /** Generate code to coerce item to given type.
         *  @param targettype    The type to coerce to.
         */
        Item coerce(Type targettype) {
            return coerce(Code.typecode(targettype));
        }

        /** Return the width of this item on stack as a number of words.
         */
        int width() {
            return 0;
        }

        public abstract String toString();
    }

    /** An item representing a value on stack.
     */
    class StackItem extends Item {

        StackItem(int typecode) {
            super(typecode);
        }

        Item load() {
            return this;
        }

        void duplicate() {
            code.emitop0(width() == 2 ? dup2 : dup);
        }

        void drop() {
            code.emitop0(width() == 2 ? pop2 : pop);
        }

        void stash(int toscode) {
            code.emitop0(
                (width() == 2 ? dup_x2 : dup_x1) + 3 * (Code.width(toscode) - 1));
        }

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

        public String toString() {
            return "stack(" + typecodeNames[typecode] + ")";
        }
    }

    /** An item representing an indexed expression.
     */
    class IndexedItem extends Item {

        IndexedItem(Type type) {
            super(Code.typecode(type));
        }

        Item load() {
            code.emitop0(iaload + typecode);
            return stackItem[typecode];
        }

        void store() {
            code.emitop0(iastore + typecode);
        }

        void duplicate() {
            code.emitop0(dup2);
        }

        void drop() {
            code.emitop0(pop2);
        }

        void stash(int toscode) {
            code.emitop0(dup_x2 + 3 * (Code.width(toscode) - 1));
        }

        int width() {
            return 2;
        }

        public String toString() {
            return "indexed(" + ByteCodes.typecodeNames[typecode] + ")";
        }
    }

    /** An item representing `this' or `super'.
     */
    class SelfItem extends Item {

        /** Flag which determines whether this item represents `this' or `super'.
         */
        boolean isSuper;

        SelfItem(boolean isSuper) {
            super(OBJECTcode);
            this.isSuper = isSuper;
        }

        Item load() {
            code.emitop0(aload_0);
            return stackItem[typecode];
        }

        public String toString() {
            return isSuper ? "super" : "this";
        }
    }

    /** An item representing a local variable.
     */
    class LocalItem extends Item {

        /** The variable's register.
         */
        int reg;

        /** The variable's type.
         */
        Type type;

        LocalItem(Type type, int reg) {
            super(Code.typecode(type));
            Assert.check(reg >= 0);
            this.type = type;
            this.reg = reg;
        }

        Item load() {
            if (reg <= 3)
                code.emitop0(iload_0 + Code.truncate(typecode) * 4 + reg);
            else
                code.emitop1w(iload + Code.truncate(typecode), reg);
            return stackItem[typecode];
        }

        void store() {
            if (reg <= 3)
                code.emitop0(istore_0 + Code.truncate(typecode) * 4 + reg);
            else
                code.emitop1w(istore + Code.truncate(typecode), reg);
            code.setDefined(reg);
        }

        void incr(int x) {
            if (typecode == INTcode && x >= -32768 && x <= 32767) {
                code.emitop1w(iinc, reg, x);
            } else {
                load();
                if (x >= 0) {
                    makeImmediateItem(syms.intType, x).load();
                    code.emitop0(iadd);
                } else {
                    makeImmediateItem(syms.intType, -x).load();
                    code.emitop0(isub);
                }
                makeStackItem(syms.intType).coerce(typecode);
                store();
            }
        }

        public String toString() {
            return "localItem(type=" + type + "; reg=" + reg + ")";
        }
    }

    /** An item representing a static variable or method.
     */
    class StaticItem extends Item {

        /** The represented symbol.
         */
        Symbol member;

        StaticItem(Symbol member) {
            super(Code.typecode(member.erasure(types)));
            this.member = member;
        }

        Item load() {
            code.emitop2(getstatic, pool.put(member));
            return stackItem[typecode];
        }

        void store() {
            code.emitop2(putstatic, pool.put(member));
        }

        Item invoke() {
            MethodType mtype = (MethodType)member.erasure(types);
            int rescode = Code.typecode(mtype.restype);
            code.emitInvokestatic(pool.put(member), mtype);
            return stackItem[rescode];
        }

        public String toString() {
            return "static(" + member + ")";
        }
    }

    /** An item representing a dynamic call site.
     */
    class DynamicItem extends StaticItem {
        DynamicItem(Symbol member) {
            super(member);
        }

        Item load() {
            assert false;
            return null;
        }

        void store() {
            assert false;
        }

        Item invoke() {
            // assert target.hasNativeInvokeDynamic();
            MethodType mtype = (MethodType)member.erasure(types);
            int rescode = Code.typecode(mtype.restype);
            code.emitInvokedynamic(pool.put(member), mtype);
            return stackItem[rescode];
        }

        public String toString() {
            return "dynamic(" + member + ")";
        }
    }

    /** An item representing an instance variable or method.
     */
    class MemberItem extends Item {

        /** The represented symbol.
         */
        Symbol member;

        /** Flag that determines whether or not access is virtual.
         */
        boolean nonvirtual;

        MemberItem(Symbol member, boolean nonvirtual) {
            super(Code.typecode(member.erasure(types)));
            this.member = member;
            this.nonvirtual = nonvirtual;
        }

        Item load() {
            code.emitop2(getfield, pool.put(member));
            return stackItem[typecode];
        }

        void store() {
            code.emitop2(putfield, pool.put(member));
        }

        Item invoke() {
            MethodType mtype = (MethodType)member.externalType(types);
            int rescode = Code.typecode(mtype.restype);
            if ((member.owner.flags() & Flags.INTERFACE) != 0 && !nonvirtual) {
                code.emitInvokeinterface(pool.put(member), mtype);
            } else if (nonvirtual) {
                code.emitInvokespecial(pool.put(member), mtype);
            } else {
                code.emitInvokevirtual(pool.put(member), mtype);
            }
            return stackItem[rescode];
        }

        void duplicate() {
            stackItem[OBJECTcode].duplicate();
        }

        void drop() {
            stackItem[OBJECTcode].drop();
        }

        void stash(int toscode) {
            stackItem[OBJECTcode].stash(toscode);
        }

        int width() {
            return 1;
        }

        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 {
                code.emitLdc(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.curCP();
            Chain c = Code.mergeChains(trueJumps, code.branch(opcode));
            code.crt.put(tree, CRTable.CRT_BRANCH_TRUE, startpc, code.curCP());
            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.curCP();
            Chain c = Code.mergeChains(falseJumps, code.branch(Code.negate(opcode)));
            code.crt.put(tree, CRTable.CRT_BRANCH_FALSE, startpc, code.curCP());
            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) + ")";
        }
    }
}
