duke@1: /* mcimadamore@1336: * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. duke@1: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. duke@1: * duke@1: * This code is free software; you can redistribute it and/or modify it duke@1: * under the terms of the GNU General Public License version 2 only, as ohair@554: * published by the Free Software Foundation. Oracle designates this duke@1: * particular file as subject to the "Classpath" exception as provided ohair@554: * by Oracle in the LICENSE file that accompanied this code. duke@1: * duke@1: * This code is distributed in the hope that it will be useful, but WITHOUT duke@1: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or duke@1: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License duke@1: * version 2 for more details (a copy is included in the LICENSE file that duke@1: * accompanied this code). duke@1: * duke@1: * You should have received a copy of the GNU General Public License version duke@1: * 2 along with this work; if not, write to the Free Software Foundation, duke@1: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. duke@1: * ohair@554: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA ohair@554: * or visit www.oracle.com if you need additional information or have any ohair@554: * questions. duke@1: */ duke@1: duke@1: package com.sun.tools.javac.jvm; duke@1: duke@1: import com.sun.tools.javac.code.*; duke@1: import com.sun.tools.javac.code.Symbol.*; duke@1: import com.sun.tools.javac.code.Type.*; duke@1: import com.sun.tools.javac.jvm.Code.*; duke@1: import com.sun.tools.javac.tree.JCTree; jjg@816: import com.sun.tools.javac.util.Assert; duke@1: duke@1: import static com.sun.tools.javac.jvm.ByteCodes.*; duke@1: duke@1: /** A helper class for code generation. Items are objects duke@1: * that stand for addressable entities in the bytecode. Each item duke@1: * supports a fixed protocol for loading the item on the stack, storing duke@1: * into it, converting it into a jump condition, and several others. duke@1: * There are many individual forms of items, such as local, static, duke@1: * indexed, or instance variables, values on the top of stack, the duke@1: * special values this or super, etc. Individual items are represented as duke@1: * inner classes in class Items. duke@1: * jjg@581: *

This is NOT part of any supported API. jjg@581: * If you write code that depends on this, you do so at your own risk. duke@1: * This code and its internal interfaces are subject to change or duke@1: * deletion without notice. duke@1: */ duke@1: public class Items { duke@1: duke@1: /** The current constant pool. duke@1: */ duke@1: Pool pool; duke@1: duke@1: /** The current code buffer. duke@1: */ duke@1: Code code; duke@1: duke@1: /** The current symbol table. duke@1: */ duke@1: Symtab syms; duke@1: duke@1: /** Type utilities. */ duke@1: Types types; duke@1: duke@1: /** Items that exist only once (flyweight pattern). duke@1: */ duke@1: private final Item voidItem; duke@1: private final Item thisItem; duke@1: private final Item superItem; duke@1: private final Item[] stackItem = new Item[TypeCodeCount]; duke@1: duke@1: public Items(Pool pool, Code code, Symtab syms, Types types) { duke@1: this.code = code; duke@1: this.pool = pool; duke@1: this.types = types; duke@1: voidItem = new Item(VOIDcode) { duke@1: public String toString() { return "void"; } duke@1: }; duke@1: thisItem = new SelfItem(false); duke@1: superItem = new SelfItem(true); duke@1: for (int i = 0; i < VOIDcode; i++) stackItem[i] = new StackItem(i); duke@1: stackItem[VOIDcode] = voidItem; duke@1: this.syms = syms; duke@1: } duke@1: duke@1: /** Make a void item duke@1: */ duke@1: Item makeVoidItem() { duke@1: return voidItem; duke@1: } duke@1: /** Make an item representing `this'. duke@1: */ duke@1: Item makeThisItem() { duke@1: return thisItem; duke@1: } duke@1: duke@1: /** Make an item representing `super'. duke@1: */ duke@1: Item makeSuperItem() { duke@1: return superItem; duke@1: } duke@1: duke@1: /** Make an item representing a value on stack. duke@1: * @param type The value's type. duke@1: */ duke@1: Item makeStackItem(Type type) { duke@1: return stackItem[Code.typecode(type)]; duke@1: } duke@1: mcimadamore@1336: /** Make an item representing a dynamically invoked method. mcimadamore@1336: * @param member The represented symbol. mcimadamore@1336: */ mcimadamore@1336: Item makeDynamicItem(Symbol member) { mcimadamore@1336: return new DynamicItem(member); mcimadamore@1336: } mcimadamore@1336: duke@1: /** Make an item representing an indexed expression. duke@1: * @param type The expression's type. duke@1: */ duke@1: Item makeIndexedItem(Type type) { duke@1: return new IndexedItem(type); duke@1: } duke@1: duke@1: /** Make an item representing a local variable. duke@1: * @param v The represented variable. duke@1: */ duke@1: LocalItem makeLocalItem(VarSymbol v) { duke@1: return new LocalItem(v.erasure(types), v.adr); duke@1: } duke@1: duke@1: /** Make an item representing a local anonymous variable. duke@1: * @param type The represented variable's type. duke@1: * @param reg The represented variable's register. duke@1: */ duke@1: private LocalItem makeLocalItem(Type type, int reg) { duke@1: return new LocalItem(type, reg); duke@1: } duke@1: duke@1: /** Make an item representing a static variable or method. duke@1: * @param member The represented symbol. duke@1: */ duke@1: Item makeStaticItem(Symbol member) { duke@1: return new StaticItem(member); duke@1: } duke@1: duke@1: /** Make an item representing an instance variable or method. duke@1: * @param member The represented symbol. duke@1: * @param nonvirtual Is the reference not virtual? (true for constructors duke@1: * and private members). duke@1: */ duke@1: Item makeMemberItem(Symbol member, boolean nonvirtual) { duke@1: return new MemberItem(member, nonvirtual); duke@1: } duke@1: duke@1: /** Make an item representing a literal. duke@1: * @param type The literal's type. duke@1: * @param value The literal's value. duke@1: */ duke@1: Item makeImmediateItem(Type type, Object value) { duke@1: return new ImmediateItem(type, value); duke@1: } duke@1: duke@1: /** Make an item representing an assignment expression. duke@1: * @param lhs The item representing the assignment's left hand side. duke@1: */ duke@1: Item makeAssignItem(Item lhs) { duke@1: return new AssignItem(lhs); duke@1: } duke@1: duke@1: /** Make an item representing a conditional or unconditional jump. duke@1: * @param opcode The jump's opcode. duke@1: * @param trueJumps A chain encomassing all jumps that can be taken duke@1: * if the condition evaluates to true. duke@1: * @param falseJumps A chain encomassing all jumps that can be taken duke@1: * if the condition evaluates to false. duke@1: */ duke@1: CondItem makeCondItem(int opcode, Chain trueJumps, Chain falseJumps) { duke@1: return new CondItem(opcode, trueJumps, falseJumps); duke@1: } duke@1: duke@1: /** Make an item representing a conditional or unconditional jump. duke@1: * @param opcode The jump's opcode. duke@1: */ duke@1: CondItem makeCondItem(int opcode) { duke@1: return makeCondItem(opcode, null, null); duke@1: } duke@1: duke@1: /** The base class of all items, which implements default behavior. duke@1: */ duke@1: abstract class Item { duke@1: duke@1: /** The type code of values represented by this item. duke@1: */ duke@1: int typecode; duke@1: duke@1: Item(int typecode) { duke@1: this.typecode = typecode; duke@1: } duke@1: duke@1: /** Generate code to load this item onto stack. duke@1: */ duke@1: Item load() { duke@1: throw new AssertionError(); duke@1: } duke@1: duke@1: /** Generate code to store top of stack into this item. duke@1: */ duke@1: void store() { duke@1: throw new AssertionError("store unsupported: " + this); duke@1: } duke@1: duke@1: /** Generate code to invoke method represented by this item. duke@1: */ duke@1: Item invoke() { duke@1: throw new AssertionError(this); duke@1: } duke@1: duke@1: /** Generate code to use this item twice. duke@1: */ duke@1: void duplicate() {} duke@1: duke@1: /** Generate code to avoid having to use this item. duke@1: */ duke@1: void drop() {} duke@1: duke@1: /** Generate code to stash a copy of top of stack - of typecode toscode - duke@1: * under this item. duke@1: */ duke@1: void stash(int toscode) { duke@1: stackItem[toscode].duplicate(); duke@1: } duke@1: duke@1: /** Generate code to turn item into a testable condition. duke@1: */ duke@1: CondItem mkCond() { duke@1: load(); duke@1: return makeCondItem(ifne); duke@1: } duke@1: duke@1: /** Generate code to coerce item to given type code. duke@1: * @param targetcode The type code to coerce to. duke@1: */ duke@1: Item coerce(int targetcode) { duke@1: if (typecode == targetcode) duke@1: return this; duke@1: else { duke@1: load(); duke@1: int typecode1 = Code.truncate(typecode); duke@1: int targetcode1 = Code.truncate(targetcode); duke@1: if (typecode1 != targetcode1) { duke@1: int offset = targetcode1 > typecode1 ? targetcode1 - 1 duke@1: : targetcode1; duke@1: code.emitop0(i2l + typecode1 * 3 + offset); duke@1: } duke@1: if (targetcode != targetcode1) { duke@1: code.emitop0(int2byte + targetcode - BYTEcode); duke@1: } duke@1: return stackItem[targetcode]; duke@1: } duke@1: } duke@1: duke@1: /** Generate code to coerce item to given type. duke@1: * @param targettype The type to coerce to. duke@1: */ duke@1: Item coerce(Type targettype) { duke@1: return coerce(Code.typecode(targettype)); duke@1: } duke@1: duke@1: /** Return the width of this item on stack as a number of words. duke@1: */ duke@1: int width() { duke@1: return 0; duke@1: } duke@1: duke@1: public abstract String toString(); duke@1: } duke@1: duke@1: /** An item representing a value on stack. duke@1: */ duke@1: class StackItem extends Item { duke@1: duke@1: StackItem(int typecode) { duke@1: super(typecode); duke@1: } duke@1: duke@1: Item load() { duke@1: return this; duke@1: } duke@1: duke@1: void duplicate() { duke@1: code.emitop0(width() == 2 ? dup2 : dup); duke@1: } duke@1: duke@1: void drop() { duke@1: code.emitop0(width() == 2 ? pop2 : pop); duke@1: } duke@1: duke@1: void stash(int toscode) { duke@1: code.emitop0( duke@1: (width() == 2 ? dup_x2 : dup_x1) + 3 * (Code.width(toscode) - 1)); duke@1: } duke@1: duke@1: int width() { duke@1: return Code.width(typecode); duke@1: } duke@1: duke@1: public String toString() { duke@1: return "stack(" + typecodeNames[typecode] + ")"; duke@1: } duke@1: } duke@1: duke@1: /** An item representing an indexed expression. duke@1: */ duke@1: class IndexedItem extends Item { duke@1: duke@1: IndexedItem(Type type) { duke@1: super(Code.typecode(type)); duke@1: } duke@1: duke@1: Item load() { duke@1: code.emitop0(iaload + typecode); duke@1: return stackItem[typecode]; duke@1: } duke@1: duke@1: void store() { duke@1: code.emitop0(iastore + typecode); duke@1: } duke@1: duke@1: void duplicate() { duke@1: code.emitop0(dup2); duke@1: } duke@1: duke@1: void drop() { duke@1: code.emitop0(pop2); duke@1: } duke@1: duke@1: void stash(int toscode) { duke@1: code.emitop0(dup_x2 + 3 * (Code.width(toscode) - 1)); duke@1: } duke@1: duke@1: int width() { duke@1: return 2; duke@1: } duke@1: duke@1: public String toString() { duke@1: return "indexed(" + ByteCodes.typecodeNames[typecode] + ")"; duke@1: } duke@1: } duke@1: duke@1: /** An item representing `this' or `super'. duke@1: */ duke@1: class SelfItem extends Item { duke@1: duke@1: /** Flag which determines whether this item represents `this' or `super'. duke@1: */ duke@1: boolean isSuper; duke@1: duke@1: SelfItem(boolean isSuper) { duke@1: super(OBJECTcode); duke@1: this.isSuper = isSuper; duke@1: } duke@1: duke@1: Item load() { duke@1: code.emitop0(aload_0); duke@1: return stackItem[typecode]; duke@1: } duke@1: duke@1: public String toString() { duke@1: return isSuper ? "super" : "this"; duke@1: } duke@1: } duke@1: duke@1: /** An item representing a local variable. duke@1: */ duke@1: class LocalItem extends Item { duke@1: duke@1: /** The variable's register. duke@1: */ duke@1: int reg; duke@1: duke@1: /** The variable's type. duke@1: */ duke@1: Type type; duke@1: duke@1: LocalItem(Type type, int reg) { duke@1: super(Code.typecode(type)); jjg@816: Assert.check(reg >= 0); duke@1: this.type = type; duke@1: this.reg = reg; duke@1: } duke@1: duke@1: Item load() { duke@1: if (reg <= 3) duke@1: code.emitop0(iload_0 + Code.truncate(typecode) * 4 + reg); duke@1: else duke@1: code.emitop1w(iload + Code.truncate(typecode), reg); duke@1: return stackItem[typecode]; duke@1: } duke@1: duke@1: void store() { duke@1: if (reg <= 3) duke@1: code.emitop0(istore_0 + Code.truncate(typecode) * 4 + reg); duke@1: else duke@1: code.emitop1w(istore + Code.truncate(typecode), reg); duke@1: code.setDefined(reg); duke@1: } duke@1: duke@1: void incr(int x) { duke@1: if (typecode == INTcode && x >= -32768 && x <= 32767) { duke@1: code.emitop1w(iinc, reg, x); duke@1: } else { duke@1: load(); duke@1: if (x >= 0) { duke@1: makeImmediateItem(syms.intType, x).load(); duke@1: code.emitop0(iadd); duke@1: } else { duke@1: makeImmediateItem(syms.intType, -x).load(); duke@1: code.emitop0(isub); duke@1: } duke@1: makeStackItem(syms.intType).coerce(typecode); duke@1: store(); duke@1: } duke@1: } duke@1: duke@1: public String toString() { duke@1: return "localItem(type=" + type + "; reg=" + reg + ")"; duke@1: } duke@1: } duke@1: duke@1: /** An item representing a static variable or method. duke@1: */ duke@1: class StaticItem extends Item { duke@1: duke@1: /** The represented symbol. duke@1: */ duke@1: Symbol member; duke@1: duke@1: StaticItem(Symbol member) { duke@1: super(Code.typecode(member.erasure(types))); duke@1: this.member = member; duke@1: } duke@1: duke@1: Item load() { duke@1: code.emitop2(getstatic, pool.put(member)); duke@1: return stackItem[typecode]; duke@1: } duke@1: duke@1: void store() { duke@1: code.emitop2(putstatic, pool.put(member)); duke@1: } duke@1: duke@1: Item invoke() { duke@1: MethodType mtype = (MethodType)member.erasure(types); duke@1: int rescode = Code.typecode(mtype.restype); duke@1: code.emitInvokestatic(pool.put(member), mtype); duke@1: return stackItem[rescode]; duke@1: } duke@1: duke@1: public String toString() { duke@1: return "static(" + member + ")"; duke@1: } duke@1: } duke@1: mcimadamore@1336: /** An item representing a dynamic call site. mcimadamore@1336: */ mcimadamore@1336: class DynamicItem extends StaticItem { mcimadamore@1336: DynamicItem(Symbol member) { mcimadamore@1336: super(member); mcimadamore@1336: } mcimadamore@1336: mcimadamore@1336: Item load() { mcimadamore@1336: assert false; mcimadamore@1336: return null; mcimadamore@1336: } mcimadamore@1336: mcimadamore@1336: void store() { mcimadamore@1336: assert false; mcimadamore@1336: } mcimadamore@1336: mcimadamore@1336: Item invoke() { mcimadamore@1336: // assert target.hasNativeInvokeDynamic(); mcimadamore@1336: MethodType mtype = (MethodType)member.erasure(types); mcimadamore@1336: int rescode = Code.typecode(mtype.restype); mcimadamore@1336: code.emitInvokedynamic(pool.put(member), mtype); mcimadamore@1336: return stackItem[rescode]; mcimadamore@1336: } mcimadamore@1336: mcimadamore@1336: public String toString() { mcimadamore@1336: return "dynamic(" + member + ")"; mcimadamore@1336: } mcimadamore@1336: } mcimadamore@1336: duke@1: /** An item representing an instance variable or method. duke@1: */ duke@1: class MemberItem extends Item { duke@1: duke@1: /** The represented symbol. duke@1: */ duke@1: Symbol member; duke@1: duke@1: /** Flag that determines whether or not access is virtual. duke@1: */ duke@1: boolean nonvirtual; duke@1: duke@1: MemberItem(Symbol member, boolean nonvirtual) { duke@1: super(Code.typecode(member.erasure(types))); duke@1: this.member = member; duke@1: this.nonvirtual = nonvirtual; duke@1: } duke@1: duke@1: Item load() { duke@1: code.emitop2(getfield, pool.put(member)); duke@1: return stackItem[typecode]; duke@1: } duke@1: duke@1: void store() { duke@1: code.emitop2(putfield, pool.put(member)); duke@1: } duke@1: duke@1: Item invoke() { duke@1: MethodType mtype = (MethodType)member.externalType(types); duke@1: int rescode = Code.typecode(mtype.restype); mcimadamore@1393: if ((member.owner.flags() & Flags.INTERFACE) != 0 && !nonvirtual) { duke@1: code.emitInvokeinterface(pool.put(member), mtype); duke@1: } else if (nonvirtual) { duke@1: code.emitInvokespecial(pool.put(member), mtype); duke@1: } else { duke@1: code.emitInvokevirtual(pool.put(member), mtype); duke@1: } duke@1: return stackItem[rescode]; duke@1: } duke@1: duke@1: void duplicate() { duke@1: stackItem[OBJECTcode].duplicate(); duke@1: } duke@1: duke@1: void drop() { duke@1: stackItem[OBJECTcode].drop(); duke@1: } duke@1: duke@1: void stash(int toscode) { duke@1: stackItem[OBJECTcode].stash(toscode); duke@1: } duke@1: duke@1: int width() { duke@1: return 1; duke@1: } duke@1: duke@1: public String toString() { duke@1: return "member(" + member + (nonvirtual ? " nonvirtual)" : ")"); duke@1: } duke@1: } duke@1: duke@1: /** An item representing a literal. duke@1: */ duke@1: class ImmediateItem extends Item { duke@1: duke@1: /** The literal's value. duke@1: */ duke@1: Object value; duke@1: duke@1: ImmediateItem(Type type, Object value) { duke@1: super(Code.typecode(type)); duke@1: this.value = value; duke@1: } duke@1: duke@1: private void ldc() { duke@1: int idx = pool.put(value); duke@1: if (typecode == LONGcode || typecode == DOUBLEcode) { duke@1: code.emitop2(ldc2w, idx); duke@1: } else if (idx <= 255) { duke@1: code.emitop1(ldc1, idx); duke@1: } else { duke@1: code.emitop2(ldc2, idx); duke@1: } duke@1: } duke@1: duke@1: Item load() { duke@1: switch (typecode) { duke@1: case INTcode: case BYTEcode: case SHORTcode: case CHARcode: duke@1: int ival = ((Number)value).intValue(); duke@1: if (-1 <= ival && ival <= 5) duke@1: code.emitop0(iconst_0 + ival); duke@1: else if (Byte.MIN_VALUE <= ival && ival <= Byte.MAX_VALUE) duke@1: code.emitop1(bipush, ival); duke@1: else if (Short.MIN_VALUE <= ival && ival <= Short.MAX_VALUE) duke@1: code.emitop2(sipush, ival); duke@1: else duke@1: ldc(); duke@1: break; duke@1: case LONGcode: duke@1: long lval = ((Number)value).longValue(); duke@1: if (lval == 0 || lval == 1) duke@1: code.emitop0(lconst_0 + (int)lval); duke@1: else duke@1: ldc(); duke@1: break; duke@1: case FLOATcode: duke@1: float fval = ((Number)value).floatValue(); duke@1: if (isPosZero(fval) || fval == 1.0 || fval == 2.0) duke@1: code.emitop0(fconst_0 + (int)fval); duke@1: else { duke@1: ldc(); duke@1: } duke@1: break; duke@1: case DOUBLEcode: duke@1: double dval = ((Number)value).doubleValue(); duke@1: if (isPosZero(dval) || dval == 1.0) duke@1: code.emitop0(dconst_0 + (int)dval); duke@1: else duke@1: ldc(); duke@1: break; duke@1: case OBJECTcode: duke@1: ldc(); duke@1: break; duke@1: default: jjg@816: Assert.error(); duke@1: } duke@1: return stackItem[typecode]; duke@1: } duke@1: //where duke@1: /** Return true iff float number is positive 0. duke@1: */ duke@1: private boolean isPosZero(float x) { duke@1: return x == 0.0f && 1.0f / x > 0.0f; duke@1: } duke@1: /** Return true iff double number is positive 0. duke@1: */ duke@1: private boolean isPosZero(double x) { duke@1: return x == 0.0d && 1.0d / x > 0.0d; duke@1: } duke@1: duke@1: CondItem mkCond() { duke@1: int ival = ((Number)value).intValue(); duke@1: return makeCondItem(ival != 0 ? goto_ : dontgoto); duke@1: } duke@1: duke@1: Item coerce(int targetcode) { duke@1: if (typecode == targetcode) { duke@1: return this; duke@1: } else { duke@1: switch (targetcode) { duke@1: case INTcode: duke@1: if (Code.truncate(typecode) == INTcode) duke@1: return this; duke@1: else duke@1: return new ImmediateItem( duke@1: syms.intType, duke@1: ((Number)value).intValue()); duke@1: case LONGcode: duke@1: return new ImmediateItem( duke@1: syms.longType, duke@1: ((Number)value).longValue()); duke@1: case FLOATcode: duke@1: return new ImmediateItem( duke@1: syms.floatType, duke@1: ((Number)value).floatValue()); duke@1: case DOUBLEcode: duke@1: return new ImmediateItem( duke@1: syms.doubleType, duke@1: ((Number)value).doubleValue()); duke@1: case BYTEcode: duke@1: return new ImmediateItem( duke@1: syms.byteType, duke@1: (int)(byte)((Number)value).intValue()); duke@1: case CHARcode: duke@1: return new ImmediateItem( duke@1: syms.charType, duke@1: (int)(char)((Number)value).intValue()); duke@1: case SHORTcode: duke@1: return new ImmediateItem( duke@1: syms.shortType, duke@1: (int)(short)((Number)value).intValue()); duke@1: default: duke@1: return super.coerce(targetcode); duke@1: } duke@1: } duke@1: } duke@1: duke@1: public String toString() { duke@1: return "immediate(" + value + ")"; duke@1: } duke@1: } duke@1: duke@1: /** An item representing an assignment expressions. duke@1: */ duke@1: class AssignItem extends Item { duke@1: duke@1: /** The item representing the assignment's left hand side. duke@1: */ duke@1: Item lhs; duke@1: duke@1: AssignItem(Item lhs) { duke@1: super(lhs.typecode); duke@1: this.lhs = lhs; duke@1: } duke@1: duke@1: Item load() { duke@1: lhs.stash(typecode); duke@1: lhs.store(); duke@1: return stackItem[typecode]; duke@1: } duke@1: duke@1: void duplicate() { duke@1: load().duplicate(); duke@1: } duke@1: duke@1: void drop() { duke@1: lhs.store(); duke@1: } duke@1: duke@1: void stash(int toscode) { jjg@816: Assert.error(); duke@1: } duke@1: duke@1: int width() { duke@1: return lhs.width() + Code.width(typecode); duke@1: } duke@1: duke@1: public String toString() { duke@1: return "assign(lhs = " + lhs + ")"; duke@1: } duke@1: } duke@1: duke@1: /** An item representing a conditional or unconditional jump. duke@1: */ duke@1: class CondItem extends Item { duke@1: duke@1: /** A chain encomassing all jumps that can be taken duke@1: * if the condition evaluates to true. duke@1: */ duke@1: Chain trueJumps; duke@1: duke@1: /** A chain encomassing all jumps that can be taken duke@1: * if the condition evaluates to false. duke@1: */ duke@1: Chain falseJumps; duke@1: duke@1: /** The jump's opcode. duke@1: */ duke@1: int opcode; duke@1: duke@1: /* duke@1: * An abstract syntax tree of this item. It is needed duke@1: * for branch entries in 'CharacterRangeTable' attribute. duke@1: */ duke@1: JCTree tree; duke@1: duke@1: CondItem(int opcode, Chain truejumps, Chain falsejumps) { duke@1: super(BYTEcode); duke@1: this.opcode = opcode; duke@1: this.trueJumps = truejumps; duke@1: this.falseJumps = falsejumps; duke@1: } duke@1: duke@1: Item load() { duke@1: Chain trueChain = null; duke@1: Chain falseChain = jumpFalse(); duke@1: if (!isFalse()) { duke@1: code.resolve(trueJumps); duke@1: code.emitop0(iconst_1); duke@1: trueChain = code.branch(goto_); duke@1: } duke@1: if (falseChain != null) { duke@1: code.resolve(falseChain); duke@1: code.emitop0(iconst_0); duke@1: } duke@1: code.resolve(trueChain); duke@1: return stackItem[typecode]; duke@1: } duke@1: duke@1: void duplicate() { duke@1: load().duplicate(); duke@1: } duke@1: duke@1: void drop() { duke@1: load().drop(); duke@1: } duke@1: duke@1: void stash(int toscode) { jjg@816: Assert.error(); duke@1: } duke@1: duke@1: CondItem mkCond() { duke@1: return this; duke@1: } duke@1: duke@1: Chain jumpTrue() { jjg@507: if (tree == null) return Code.mergeChains(trueJumps, code.branch(opcode)); duke@1: // we should proceed further in -Xjcov mode only duke@1: int startpc = code.curPc(); jjg@507: Chain c = Code.mergeChains(trueJumps, code.branch(opcode)); duke@1: code.crt.put(tree, CRTable.CRT_BRANCH_TRUE, startpc, code.curPc()); duke@1: return c; duke@1: } duke@1: duke@1: Chain jumpFalse() { jjg@507: if (tree == null) return Code.mergeChains(falseJumps, code.branch(Code.negate(opcode))); duke@1: // we should proceed further in -Xjcov mode only duke@1: int startpc = code.curPc(); jjg@507: Chain c = Code.mergeChains(falseJumps, code.branch(Code.negate(opcode))); duke@1: code.crt.put(tree, CRTable.CRT_BRANCH_FALSE, startpc, code.curPc()); duke@1: return c; duke@1: } duke@1: duke@1: CondItem negate() { jjg@507: CondItem c = new CondItem(Code.negate(opcode), falseJumps, trueJumps); duke@1: c.tree = tree; duke@1: return c; duke@1: } duke@1: duke@1: int width() { duke@1: // a CondItem doesn't have a size on the stack per se. duke@1: throw new AssertionError(); duke@1: } duke@1: duke@1: boolean isTrue() { duke@1: return falseJumps == null && opcode == goto_; duke@1: } duke@1: duke@1: boolean isFalse() { duke@1: return trueJumps == null && opcode == dontgoto; duke@1: } duke@1: duke@1: public String toString() { duke@1: return "cond(" + Code.mnem(opcode) + ")"; duke@1: } duke@1: } duke@1: }