0N/A/*
815N/A * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
553N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
553N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
553N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
553N/A * or visit www.oracle.com if you need additional information or have any
553N/A * questions.
0N/A */
0N/A
0N/Apackage com.sun.tools.javac.jvm;
0N/A
0N/Aimport com.sun.tools.javac.code.*;
0N/Aimport com.sun.tools.javac.code.Symbol.*;
0N/Aimport com.sun.tools.javac.code.Type.*;
0N/Aimport com.sun.tools.javac.jvm.Code.*;
0N/Aimport com.sun.tools.javac.tree.JCTree;
815N/Aimport com.sun.tools.javac.util.Assert;
0N/A
0N/Aimport static com.sun.tools.javac.jvm.ByteCodes.*;
0N/A
0N/A/** A helper class for code generation. Items are objects
0N/A * that stand for addressable entities in the bytecode. Each item
0N/A * supports a fixed protocol for loading the item on the stack, storing
0N/A * into it, converting it into a jump condition, and several others.
0N/A * There are many individual forms of items, such as local, static,
0N/A * indexed, or instance variables, values on the top of stack, the
0N/A * special values this or super, etc. Individual items are represented as
0N/A * inner classes in class Items.
0N/A *
580N/A * <p><b>This is NOT part of any supported API.
580N/A * If you write code that depends on this, you do so at your own risk.
0N/A * This code and its internal interfaces are subject to change or
0N/A * deletion without notice.</b>
0N/A */
0N/Apublic class Items {
0N/A
0N/A /** The current constant pool.
0N/A */
0N/A Pool pool;
0N/A
0N/A /** The current code buffer.
0N/A */
0N/A Code code;
0N/A
0N/A /** The current symbol table.
0N/A */
0N/A Symtab syms;
0N/A
0N/A /** Type utilities. */
0N/A Types types;
0N/A
0N/A /** Items that exist only once (flyweight pattern).
0N/A */
0N/A private final Item voidItem;
0N/A private final Item thisItem;
0N/A private final Item superItem;
0N/A private final Item[] stackItem = new Item[TypeCodeCount];
0N/A
0N/A public Items(Pool pool, Code code, Symtab syms, Types types) {
0N/A this.code = code;
0N/A this.pool = pool;
0N/A this.types = types;
0N/A voidItem = new Item(VOIDcode) {
0N/A public String toString() { return "void"; }
0N/A };
0N/A thisItem = new SelfItem(false);
0N/A superItem = new SelfItem(true);
0N/A for (int i = 0; i < VOIDcode; i++) stackItem[i] = new StackItem(i);
0N/A stackItem[VOIDcode] = voidItem;
0N/A this.syms = syms;
0N/A }
0N/A
0N/A /** Make a void item
0N/A */
0N/A Item makeVoidItem() {
0N/A return voidItem;
0N/A }
0N/A /** Make an item representing `this'.
0N/A */
0N/A Item makeThisItem() {
0N/A return thisItem;
0N/A }
0N/A
0N/A /** Make an item representing `super'.
0N/A */
0N/A Item makeSuperItem() {
0N/A return superItem;
0N/A }
0N/A
0N/A /** Make an item representing a value on stack.
0N/A * @param type The value's type.
0N/A */
0N/A Item makeStackItem(Type type) {
0N/A return stackItem[Code.typecode(type)];
0N/A }
0N/A
0N/A /** Make an item representing an indexed expression.
0N/A * @param type The expression's type.
0N/A */
0N/A Item makeIndexedItem(Type type) {
0N/A return new IndexedItem(type);
0N/A }
0N/A
0N/A /** Make an item representing a local variable.
0N/A * @param v The represented variable.
0N/A */
0N/A LocalItem makeLocalItem(VarSymbol v) {
0N/A return new LocalItem(v.erasure(types), v.adr);
0N/A }
0N/A
0N/A /** Make an item representing a local anonymous variable.
0N/A * @param type The represented variable's type.
0N/A * @param reg The represented variable's register.
0N/A */
0N/A private LocalItem makeLocalItem(Type type, int reg) {
0N/A return new LocalItem(type, reg);
0N/A }
0N/A
0N/A /** Make an item representing a static variable or method.
0N/A * @param member The represented symbol.
0N/A */
0N/A Item makeStaticItem(Symbol member) {
0N/A return new StaticItem(member);
0N/A }
0N/A
0N/A /** Make an item representing an instance variable or method.
0N/A * @param member The represented symbol.
0N/A * @param nonvirtual Is the reference not virtual? (true for constructors
0N/A * and private members).
0N/A */
0N/A Item makeMemberItem(Symbol member, boolean nonvirtual) {
0N/A return new MemberItem(member, nonvirtual);
0N/A }
0N/A
0N/A /** Make an item representing a literal.
0N/A * @param type The literal's type.
0N/A * @param value The literal's value.
0N/A */
0N/A Item makeImmediateItem(Type type, Object value) {
0N/A return new ImmediateItem(type, value);
0N/A }
0N/A
0N/A /** Make an item representing an assignment expression.
0N/A * @param lhs The item representing the assignment's left hand side.
0N/A */
0N/A Item makeAssignItem(Item lhs) {
0N/A return new AssignItem(lhs);
0N/A }
0N/A
0N/A /** Make an item representing a conditional or unconditional jump.
0N/A * @param opcode The jump's opcode.
0N/A * @param trueJumps A chain encomassing all jumps that can be taken
0N/A * if the condition evaluates to true.
0N/A * @param falseJumps A chain encomassing all jumps that can be taken
0N/A * if the condition evaluates to false.
0N/A */
0N/A CondItem makeCondItem(int opcode, Chain trueJumps, Chain falseJumps) {
0N/A return new CondItem(opcode, trueJumps, falseJumps);
0N/A }
0N/A
0N/A /** Make an item representing a conditional or unconditional jump.
0N/A * @param opcode The jump's opcode.
0N/A */
0N/A CondItem makeCondItem(int opcode) {
0N/A return makeCondItem(opcode, null, null);
0N/A }
0N/A
0N/A /** The base class of all items, which implements default behavior.
0N/A */
0N/A abstract class Item {
0N/A
0N/A /** The type code of values represented by this item.
0N/A */
0N/A int typecode;
0N/A
0N/A Item(int typecode) {
0N/A this.typecode = typecode;
0N/A }
0N/A
0N/A /** Generate code to load this item onto stack.
0N/A */
0N/A Item load() {
0N/A throw new AssertionError();
0N/A }
0N/A
0N/A /** Generate code to store top of stack into this item.
0N/A */
0N/A void store() {
0N/A throw new AssertionError("store unsupported: " + this);
0N/A }
0N/A
0N/A /** Generate code to invoke method represented by this item.
0N/A */
0N/A Item invoke() {
0N/A throw new AssertionError(this);
0N/A }
0N/A
0N/A /** Generate code to use this item twice.
0N/A */
0N/A void duplicate() {}
0N/A
0N/A /** Generate code to avoid having to use this item.
0N/A */
0N/A void drop() {}
0N/A
0N/A /** Generate code to stash a copy of top of stack - of typecode toscode -
0N/A * under this item.
0N/A */
0N/A void stash(int toscode) {
0N/A stackItem[toscode].duplicate();
0N/A }
0N/A
0N/A /** Generate code to turn item into a testable condition.
0N/A */
0N/A CondItem mkCond() {
0N/A load();
0N/A return makeCondItem(ifne);
0N/A }
0N/A
0N/A /** Generate code to coerce item to given type code.
0N/A * @param targetcode The type code to coerce to.
0N/A */
0N/A Item coerce(int targetcode) {
0N/A if (typecode == targetcode)
0N/A return this;
0N/A else {
0N/A load();
0N/A int typecode1 = Code.truncate(typecode);
0N/A int targetcode1 = Code.truncate(targetcode);
0N/A if (typecode1 != targetcode1) {
0N/A int offset = targetcode1 > typecode1 ? targetcode1 - 1
0N/A : targetcode1;
0N/A code.emitop0(i2l + typecode1 * 3 + offset);
0N/A }
0N/A if (targetcode != targetcode1) {
0N/A code.emitop0(int2byte + targetcode - BYTEcode);
0N/A }
0N/A return stackItem[targetcode];
0N/A }
0N/A }
0N/A
0N/A /** Generate code to coerce item to given type.
0N/A * @param targettype The type to coerce to.
0N/A */
0N/A Item coerce(Type targettype) {
0N/A return coerce(Code.typecode(targettype));
0N/A }
0N/A
0N/A /** Return the width of this item on stack as a number of words.
0N/A */
0N/A int width() {
0N/A return 0;
0N/A }
0N/A
0N/A public abstract String toString();
0N/A }
0N/A
0N/A /** An item representing a value on stack.
0N/A */
0N/A class StackItem extends Item {
0N/A
0N/A StackItem(int typecode) {
0N/A super(typecode);
0N/A }
0N/A
0N/A Item load() {
0N/A return this;
0N/A }
0N/A
0N/A void duplicate() {
0N/A code.emitop0(width() == 2 ? dup2 : dup);
0N/A }
0N/A
0N/A void drop() {
0N/A code.emitop0(width() == 2 ? pop2 : pop);
0N/A }
0N/A
0N/A void stash(int toscode) {
0N/A code.emitop0(
0N/A (width() == 2 ? dup_x2 : dup_x1) + 3 * (Code.width(toscode) - 1));
0N/A }
0N/A
0N/A int width() {
0N/A return Code.width(typecode);
0N/A }
0N/A
0N/A public String toString() {
0N/A return "stack(" + typecodeNames[typecode] + ")";
0N/A }
0N/A }
0N/A
0N/A /** An item representing an indexed expression.
0N/A */
0N/A class IndexedItem extends Item {
0N/A
0N/A IndexedItem(Type type) {
0N/A super(Code.typecode(type));
0N/A }
0N/A
0N/A Item load() {
0N/A code.emitop0(iaload + typecode);
0N/A return stackItem[typecode];
0N/A }
0N/A
0N/A void store() {
0N/A code.emitop0(iastore + typecode);
0N/A }
0N/A
0N/A void duplicate() {
0N/A code.emitop0(dup2);
0N/A }
0N/A
0N/A void drop() {
0N/A code.emitop0(pop2);
0N/A }
0N/A
0N/A void stash(int toscode) {
0N/A code.emitop0(dup_x2 + 3 * (Code.width(toscode) - 1));
0N/A }
0N/A
0N/A int width() {
0N/A return 2;
0N/A }
0N/A
0N/A public String toString() {
0N/A return "indexed(" + ByteCodes.typecodeNames[typecode] + ")";
0N/A }
0N/A }
0N/A
0N/A /** An item representing `this' or `super'.
0N/A */
0N/A class SelfItem extends Item {
0N/A
0N/A /** Flag which determines whether this item represents `this' or `super'.
0N/A */
0N/A boolean isSuper;
0N/A
0N/A SelfItem(boolean isSuper) {
0N/A super(OBJECTcode);
0N/A this.isSuper = isSuper;
0N/A }
0N/A
0N/A Item load() {
0N/A code.emitop0(aload_0);
0N/A return stackItem[typecode];
0N/A }
0N/A
0N/A public String toString() {
0N/A return isSuper ? "super" : "this";
0N/A }
0N/A }
0N/A
0N/A /** An item representing a local variable.
0N/A */
0N/A class LocalItem extends Item {
0N/A
0N/A /** The variable's register.
0N/A */
0N/A int reg;
0N/A
0N/A /** The variable's type.
0N/A */
0N/A Type type;
0N/A
0N/A LocalItem(Type type, int reg) {
0N/A super(Code.typecode(type));
815N/A Assert.check(reg >= 0);
0N/A this.type = type;
0N/A this.reg = reg;
0N/A }
0N/A
0N/A Item load() {
0N/A if (reg <= 3)
0N/A code.emitop0(iload_0 + Code.truncate(typecode) * 4 + reg);
0N/A else
0N/A code.emitop1w(iload + Code.truncate(typecode), reg);
0N/A return stackItem[typecode];
0N/A }
0N/A
0N/A void store() {
0N/A if (reg <= 3)
0N/A code.emitop0(istore_0 + Code.truncate(typecode) * 4 + reg);
0N/A else
0N/A code.emitop1w(istore + Code.truncate(typecode), reg);
0N/A code.setDefined(reg);
0N/A }
0N/A
0N/A void incr(int x) {
0N/A if (typecode == INTcode && x >= -32768 && x <= 32767) {
0N/A code.emitop1w(iinc, reg, x);
0N/A } else {
0N/A load();
0N/A if (x >= 0) {
0N/A makeImmediateItem(syms.intType, x).load();
0N/A code.emitop0(iadd);
0N/A } else {
0N/A makeImmediateItem(syms.intType, -x).load();
0N/A code.emitop0(isub);
0N/A }
0N/A makeStackItem(syms.intType).coerce(typecode);
0N/A store();
0N/A }
0N/A }
0N/A
0N/A public String toString() {
0N/A return "localItem(type=" + type + "; reg=" + reg + ")";
0N/A }
0N/A }
0N/A
0N/A /** An item representing a static variable or method.
0N/A */
0N/A class StaticItem extends Item {
0N/A
0N/A /** The represented symbol.
0N/A */
0N/A Symbol member;
0N/A
0N/A StaticItem(Symbol member) {
0N/A super(Code.typecode(member.erasure(types)));
0N/A this.member = member;
0N/A }
0N/A
0N/A Item load() {
0N/A code.emitop2(getstatic, pool.put(member));
0N/A return stackItem[typecode];
0N/A }
0N/A
0N/A void store() {
0N/A code.emitop2(putstatic, pool.put(member));
0N/A }
0N/A
0N/A Item invoke() {
0N/A MethodType mtype = (MethodType)member.erasure(types);
0N/A int rescode = Code.typecode(mtype.restype);
0N/A code.emitInvokestatic(pool.put(member), mtype);
0N/A return stackItem[rescode];
0N/A }
0N/A
0N/A public String toString() {
0N/A return "static(" + member + ")";
0N/A }
0N/A }
0N/A
0N/A /** An item representing an instance variable or method.
0N/A */
0N/A class MemberItem extends Item {
0N/A
0N/A /** The represented symbol.
0N/A */
0N/A Symbol member;
0N/A
0N/A /** Flag that determines whether or not access is virtual.
0N/A */
0N/A boolean nonvirtual;
0N/A
0N/A MemberItem(Symbol member, boolean nonvirtual) {
0N/A super(Code.typecode(member.erasure(types)));
0N/A this.member = member;
0N/A this.nonvirtual = nonvirtual;
0N/A }
0N/A
0N/A Item load() {
0N/A code.emitop2(getfield, pool.put(member));
0N/A return stackItem[typecode];
0N/A }
0N/A
0N/A void store() {
0N/A code.emitop2(putfield, pool.put(member));
0N/A }
0N/A
0N/A Item invoke() {
0N/A MethodType mtype = (MethodType)member.externalType(types);
0N/A int rescode = Code.typecode(mtype.restype);
0N/A if ((member.owner.flags() & Flags.INTERFACE) != 0) {
0N/A code.emitInvokeinterface(pool.put(member), mtype);
0N/A } else if (nonvirtual) {
0N/A code.emitInvokespecial(pool.put(member), mtype);
0N/A } else {
0N/A code.emitInvokevirtual(pool.put(member), mtype);
0N/A }
0N/A return stackItem[rescode];
0N/A }
0N/A
0N/A void duplicate() {
0N/A stackItem[OBJECTcode].duplicate();
0N/A }
0N/A
0N/A void drop() {
0N/A stackItem[OBJECTcode].drop();
0N/A }
0N/A
0N/A void stash(int toscode) {
0N/A stackItem[OBJECTcode].stash(toscode);
0N/A }
0N/A
0N/A int width() {
0N/A return 1;
0N/A }
0N/A
0N/A public String toString() {
0N/A return "member(" + member + (nonvirtual ? " nonvirtual)" : ")");
0N/A }
0N/A }
0N/A
0N/A /** An item representing a literal.
0N/A */
0N/A class ImmediateItem extends Item {
0N/A
0N/A /** The literal's value.
0N/A */
0N/A Object value;
0N/A
0N/A ImmediateItem(Type type, Object value) {
0N/A super(Code.typecode(type));
0N/A this.value = value;
0N/A }
0N/A
0N/A private void ldc() {
0N/A int idx = pool.put(value);
0N/A if (typecode == LONGcode || typecode == DOUBLEcode) {
0N/A code.emitop2(ldc2w, idx);
0N/A } else if (idx <= 255) {
0N/A code.emitop1(ldc1, idx);
0N/A } else {
0N/A code.emitop2(ldc2, idx);
0N/A }
0N/A }
0N/A
0N/A Item load() {
0N/A switch (typecode) {
0N/A case INTcode: case BYTEcode: case SHORTcode: case CHARcode:
0N/A int ival = ((Number)value).intValue();
0N/A if (-1 <= ival && ival <= 5)
0N/A code.emitop0(iconst_0 + ival);
0N/A else if (Byte.MIN_VALUE <= ival && ival <= Byte.MAX_VALUE)
0N/A code.emitop1(bipush, ival);
0N/A else if (Short.MIN_VALUE <= ival && ival <= Short.MAX_VALUE)
0N/A code.emitop2(sipush, ival);
0N/A else
0N/A ldc();
0N/A break;
0N/A case LONGcode:
0N/A long lval = ((Number)value).longValue();
0N/A if (lval == 0 || lval == 1)
0N/A code.emitop0(lconst_0 + (int)lval);
0N/A else
0N/A ldc();
0N/A break;
0N/A case FLOATcode:
0N/A float fval = ((Number)value).floatValue();
0N/A if (isPosZero(fval) || fval == 1.0 || fval == 2.0)
0N/A code.emitop0(fconst_0 + (int)fval);
0N/A else {
0N/A ldc();
0N/A }
0N/A break;
0N/A case DOUBLEcode:
0N/A double dval = ((Number)value).doubleValue();
0N/A if (isPosZero(dval) || dval == 1.0)
0N/A code.emitop0(dconst_0 + (int)dval);
0N/A else
0N/A ldc();
0N/A break;
0N/A case OBJECTcode:
0N/A ldc();
0N/A break;
0N/A default:
815N/A Assert.error();
0N/A }
0N/A return stackItem[typecode];
0N/A }
0N/A //where
0N/A /** Return true iff float number is positive 0.
0N/A */
0N/A private boolean isPosZero(float x) {
0N/A return x == 0.0f && 1.0f / x > 0.0f;
0N/A }
0N/A /** Return true iff double number is positive 0.
0N/A */
0N/A private boolean isPosZero(double x) {
0N/A return x == 0.0d && 1.0d / x > 0.0d;
0N/A }
0N/A
0N/A CondItem mkCond() {
0N/A int ival = ((Number)value).intValue();
0N/A return makeCondItem(ival != 0 ? goto_ : dontgoto);
0N/A }
0N/A
0N/A Item coerce(int targetcode) {
0N/A if (typecode == targetcode) {
0N/A return this;
0N/A } else {
0N/A switch (targetcode) {
0N/A case INTcode:
0N/A if (Code.truncate(typecode) == INTcode)
0N/A return this;
0N/A else
0N/A return new ImmediateItem(
0N/A syms.intType,
0N/A ((Number)value).intValue());
0N/A case LONGcode:
0N/A return new ImmediateItem(
0N/A syms.longType,
0N/A ((Number)value).longValue());
0N/A case FLOATcode:
0N/A return new ImmediateItem(
0N/A syms.floatType,
0N/A ((Number)value).floatValue());
0N/A case DOUBLEcode:
0N/A return new ImmediateItem(
0N/A syms.doubleType,
0N/A ((Number)value).doubleValue());
0N/A case BYTEcode:
0N/A return new ImmediateItem(
0N/A syms.byteType,
0N/A (int)(byte)((Number)value).intValue());
0N/A case CHARcode:
0N/A return new ImmediateItem(
0N/A syms.charType,
0N/A (int)(char)((Number)value).intValue());
0N/A case SHORTcode:
0N/A return new ImmediateItem(
0N/A syms.shortType,
0N/A (int)(short)((Number)value).intValue());
0N/A default:
0N/A return super.coerce(targetcode);
0N/A }
0N/A }
0N/A }
0N/A
0N/A public String toString() {
0N/A return "immediate(" + value + ")";
0N/A }
0N/A }
0N/A
0N/A /** An item representing an assignment expressions.
0N/A */
0N/A class AssignItem extends Item {
0N/A
0N/A /** The item representing the assignment's left hand side.
0N/A */
0N/A Item lhs;
0N/A
0N/A AssignItem(Item lhs) {
0N/A super(lhs.typecode);
0N/A this.lhs = lhs;
0N/A }
0N/A
0N/A Item load() {
0N/A lhs.stash(typecode);
0N/A lhs.store();
0N/A return stackItem[typecode];
0N/A }
0N/A
0N/A void duplicate() {
0N/A load().duplicate();
0N/A }
0N/A
0N/A void drop() {
0N/A lhs.store();
0N/A }
0N/A
0N/A void stash(int toscode) {
815N/A Assert.error();
0N/A }
0N/A
0N/A int width() {
0N/A return lhs.width() + Code.width(typecode);
0N/A }
0N/A
0N/A public String toString() {
0N/A return "assign(lhs = " + lhs + ")";
0N/A }
0N/A }
0N/A
0N/A /** An item representing a conditional or unconditional jump.
0N/A */
0N/A class CondItem extends Item {
0N/A
0N/A /** A chain encomassing all jumps that can be taken
0N/A * if the condition evaluates to true.
0N/A */
0N/A Chain trueJumps;
0N/A
0N/A /** A chain encomassing all jumps that can be taken
0N/A * if the condition evaluates to false.
0N/A */
0N/A Chain falseJumps;
0N/A
0N/A /** The jump's opcode.
0N/A */
0N/A int opcode;
0N/A
0N/A /*
0N/A * An abstract syntax tree of this item. It is needed
0N/A * for branch entries in 'CharacterRangeTable' attribute.
0N/A */
0N/A JCTree tree;
0N/A
0N/A CondItem(int opcode, Chain truejumps, Chain falsejumps) {
0N/A super(BYTEcode);
0N/A this.opcode = opcode;
0N/A this.trueJumps = truejumps;
0N/A this.falseJumps = falsejumps;
0N/A }
0N/A
0N/A Item load() {
0N/A Chain trueChain = null;
0N/A Chain falseChain = jumpFalse();
0N/A if (!isFalse()) {
0N/A code.resolve(trueJumps);
0N/A code.emitop0(iconst_1);
0N/A trueChain = code.branch(goto_);
0N/A }
0N/A if (falseChain != null) {
0N/A code.resolve(falseChain);
0N/A code.emitop0(iconst_0);
0N/A }
0N/A code.resolve(trueChain);
0N/A return stackItem[typecode];
0N/A }
0N/A
0N/A void duplicate() {
0N/A load().duplicate();
0N/A }
0N/A
0N/A void drop() {
0N/A load().drop();
0N/A }
0N/A
0N/A void stash(int toscode) {
815N/A Assert.error();
0N/A }
0N/A
0N/A CondItem mkCond() {
0N/A return this;
0N/A }
0N/A
0N/A Chain jumpTrue() {
506N/A if (tree == null) return Code.mergeChains(trueJumps, code.branch(opcode));
0N/A // we should proceed further in -Xjcov mode only
0N/A int startpc = code.curPc();
506N/A Chain c = Code.mergeChains(trueJumps, code.branch(opcode));
0N/A code.crt.put(tree, CRTable.CRT_BRANCH_TRUE, startpc, code.curPc());
0N/A return c;
0N/A }
0N/A
0N/A Chain jumpFalse() {
506N/A if (tree == null) return Code.mergeChains(falseJumps, code.branch(Code.negate(opcode)));
0N/A // we should proceed further in -Xjcov mode only
0N/A int startpc = code.curPc();
506N/A Chain c = Code.mergeChains(falseJumps, code.branch(Code.negate(opcode)));
0N/A code.crt.put(tree, CRTable.CRT_BRANCH_FALSE, startpc, code.curPc());
0N/A return c;
0N/A }
0N/A
0N/A CondItem negate() {
506N/A CondItem c = new CondItem(Code.negate(opcode), falseJumps, trueJumps);
0N/A c.tree = tree;
0N/A return c;
0N/A }
0N/A
0N/A int width() {
0N/A // a CondItem doesn't have a size on the stack per se.
0N/A throw new AssertionError();
0N/A }
0N/A
0N/A boolean isTrue() {
0N/A return falseJumps == null && opcode == goto_;
0N/A }
0N/A
0N/A boolean isFalse() {
0N/A return trueJumps == null && opcode == dontgoto;
0N/A }
0N/A
0N/A public String toString() {
0N/A return "cond(" + Code.mnem(opcode) + ")";
0N/A }
0N/A }
0N/A}