1 /*
   2  * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.tools.javac.jvm;
  27 
  28 import com.sun.tools.javac.code.*;
  29 import com.sun.tools.javac.code.Kinds.Kind;
  30 import com.sun.tools.javac.code.Symbol.*;
  31 import com.sun.tools.javac.code.Type.*;
  32 import com.sun.tools.javac.jvm.Code.*;
  33 import com.sun.tools.javac.jvm.Pool.DynamicVariable;
  34 import com.sun.tools.javac.tree.JCTree;
  35 import com.sun.tools.javac.util.Assert;
  36 
  37 import static com.sun.tools.javac.jvm.ByteCodes.*;
  38 
  39 /** A helper class for code generation. Items are objects
  40  *  that stand for addressable entities in the bytecode. Each item
  41  *  supports a fixed protocol for loading the item on the stack, storing
  42  *  into it, converting it into a jump condition, and several others.
  43  *  There are many individual forms of items, such as local, static,
  44  *  indexed, or instance variables, values on the top of stack, the
  45  *  special values this or super, etc. Individual items are represented as
  46  *  inner classes in class Items.
  47  *
  48  *  <p><b>This is NOT part of any supported API.
  49  *  If you write code that depends on this, you do so at your own risk.
  50  *  This code and its internal interfaces are subject to change or
  51  *  deletion without notice.</b>
  52  */
  53 public class Items {
  54 
  55     /** The current constant pool.
  56      */
  57     Pool pool;
  58 
  59     /** The current code buffer.
  60      */
  61     Code code;
  62 
  63     /** The current symbol table.
  64      */
  65     Symtab syms;
  66 
  67     /** Type utilities. */
  68     Types types;
  69 
  70     /** Items that exist only once (flyweight pattern).
  71      */
  72     private final Item voidItem;
  73     private final Item thisItem;
  74     private final Item superItem;
  75     private final Item[] stackItem = new Item[TypeCodeCount];
  76 
  77     public Items(Pool pool, Code code, Symtab syms, Types types) {
  78         this.code = code;
  79         this.pool = pool;
  80         this.types = types;
  81         voidItem = new Item(VOIDcode) {
  82                 public String toString() { return "void"; }
  83             };
  84         thisItem = new SelfItem(false);
  85         superItem = new SelfItem(true);
  86         for (int i = 0; i < VOIDcode; i++) stackItem[i] = new StackItem(i);
  87         stackItem[VOIDcode] = voidItem;
  88         this.syms = syms;
  89     }
  90 
  91     /** Make a void item
  92      */
  93     Item makeVoidItem() {
  94         return voidItem;
  95     }
  96     /** Make an item representing `this'.
  97      */
  98     Item makeThisItem() {
  99         return thisItem;
 100     }
 101 
 102     /** Make an item representing `super'.
 103      */
 104     Item makeSuperItem() {
 105         return superItem;
 106     }
 107 
 108     /** Make an item representing a value on stack.
 109      *  @param type    The value's type.
 110      */
 111     Item makeStackItem(Type type) {
 112         return stackItem[Code.typecode(type)];
 113     }
 114 
 115     /** Make an item representing a dynamically invoked method.
 116      *  @param member   The represented symbol.
 117      */
 118     Item makeDynamicItem(Symbol member) {
 119         return new DynamicItem(member);
 120     }
 121 
 122     /** Make an item representing an indexed expression.
 123      *  @param type    The expression's type.
 124      */
 125     Item makeIndexedItem(Type type) {
 126         return new IndexedItem(type);
 127     }
 128 
 129     /** Make an item representing a local variable.
 130      *  @param v    The represented variable.
 131      */
 132     LocalItem makeLocalItem(VarSymbol v) {
 133         return new LocalItem(v.erasure(types), v.adr);
 134     }
 135 
 136     /** Make an item representing a local anonymous variable.
 137      *  @param type  The represented variable's type.
 138      *  @param reg   The represented variable's register.
 139      */
 140     private LocalItem makeLocalItem(Type type, int reg) {
 141         return new LocalItem(type, reg);
 142     }
 143 
 144     /** Make an item representing a static variable or method.
 145      *  @param member   The represented symbol.
 146      */
 147     Item makeStaticItem(Symbol member) {
 148         return new StaticItem(member);
 149     }
 150 
 151     /** Make an item representing an instance variable or method.
 152      *  @param member       The represented symbol.
 153      *  @param nonvirtual   Is the reference not virtual? (true for constructors
 154      *                      and private members).
 155      */
 156     Item makeMemberItem(Symbol member, boolean nonvirtual) {
 157         return new MemberItem(member, nonvirtual);
 158     }
 159 
 160     /** Make an item representing a literal.
 161      *  @param type     The literal's type.
 162      *  @param value    The literal's value.
 163      */
 164     Item makeImmediateItem(Type type, Object value) {
 165         return new ImmediateItem(type, value);
 166     }
 167 
 168     /** Make an item representing a condy.
 169      *  @param value    The condy value.
 170      */
 171     Item makeCondyItem(DynamicVariable value) {
 172         return new CondyItem(value);
 173     }
 174 
 175     /** Make an item representing an assignment expression.
 176      *  @param lhs      The item representing the assignment's left hand side.
 177      */
 178     Item makeAssignItem(Item lhs) {
 179         return new AssignItem(lhs);
 180     }
 181 
 182     /** Make an item representing a conditional or unconditional jump.
 183      *  @param opcode      The jump's opcode.
 184      *  @param trueJumps   A chain encomassing all jumps that can be taken
 185      *                     if the condition evaluates to true.
 186      *  @param falseJumps  A chain encomassing all jumps that can be taken
 187      *                     if the condition evaluates to false.
 188      */
 189     CondItem makeCondItem(int opcode, Chain trueJumps, Chain falseJumps) {
 190         return new CondItem(opcode, trueJumps, falseJumps);
 191     }
 192 
 193     /** Make an item representing a conditional or unconditional jump.
 194      *  @param opcode      The jump's opcode.
 195      */
 196     CondItem makeCondItem(int opcode) {
 197         return makeCondItem(opcode, null, null);
 198     }
 199 
 200     /** The base class of all items, which implements default behavior.
 201      */
 202     abstract class Item {
 203 
 204         /** The type code of values represented by this item.
 205          */
 206         int typecode;
 207 
 208         Item(int typecode) {
 209             this.typecode = typecode;
 210         }
 211 
 212         /** Generate code to load this item onto stack.
 213          */
 214         Item load() {
 215             throw new AssertionError();
 216         }
 217 
 218         /** Generate code to store top of stack into this item.
 219          */
 220         void store() {
 221             throw new AssertionError("store unsupported: " + this);
 222         }
 223 
 224         /** Generate code to invoke method represented by this item.
 225          */
 226         Item invoke() {
 227             throw new AssertionError(this);
 228         }
 229 
 230         /** Generate code to use this item twice.
 231          */
 232         void duplicate() {}
 233 
 234         /** Generate code to avoid having to use this item.
 235          */
 236         void drop() {}
 237 
 238         /** Generate code to stash a copy of top of stack - of typecode toscode -
 239          *  under this item.
 240          */
 241         void stash(int toscode) {
 242             stackItem[toscode].duplicate();
 243         }
 244 
 245         /** Generate code to turn item into a testable condition.
 246          */
 247         CondItem mkCond() {
 248             load();
 249             return makeCondItem(ifne);
 250         }
 251 
 252         /** Generate code to coerce item to given type code.
 253          *  @param targetcode    The type code to coerce to.
 254          */
 255         Item coerce(int targetcode) {
 256             if (typecode == targetcode)
 257                 return this;
 258             else {
 259                 load();
 260                 int typecode1 = Code.truncate(typecode);
 261                 int targetcode1 = Code.truncate(targetcode);
 262                 if (typecode1 != targetcode1) {
 263                     int offset = targetcode1 > typecode1 ? targetcode1 - 1
 264                         : targetcode1;
 265                     code.emitop0(i2l + typecode1 * 3 + offset);
 266                 }
 267                 if (targetcode != targetcode1) {
 268                     code.emitop0(int2byte + targetcode - BYTEcode);
 269                 }
 270                 return stackItem[targetcode];
 271             }
 272         }
 273 
 274         /** Generate code to coerce item to given type.
 275          *  @param targettype    The type to coerce to.
 276          */
 277         Item coerce(Type targettype) {
 278             return coerce(Code.typecode(targettype));
 279         }
 280 
 281         /** Return the width of this item on stack as a number of words.
 282          */
 283         int width() {
 284             return 0;
 285         }
 286 
 287         public abstract String toString();
 288     }
 289 
 290     /** An item representing a value on stack.
 291      */
 292     class StackItem extends Item {
 293 
 294         StackItem(int typecode) {
 295             super(typecode);
 296         }
 297 
 298         Item load() {
 299             return this;
 300         }
 301 
 302         void duplicate() {
 303             code.emitop0(width() == 2 ? dup2 : dup);
 304         }
 305 
 306         void drop() {
 307             code.emitop0(width() == 2 ? pop2 : pop);
 308         }
 309 
 310         void stash(int toscode) {
 311             code.emitop0(
 312                 (width() == 2 ? dup_x2 : dup_x1) + 3 * (Code.width(toscode) - 1));
 313         }
 314 
 315         int width() {
 316             return Code.width(typecode);
 317         }
 318 
 319         public String toString() {
 320             return "stack(" + typecodeNames[typecode] + ")";
 321         }
 322     }
 323 
 324     /** An item representing an indexed expression.
 325      */
 326     class IndexedItem extends Item {
 327 
 328         IndexedItem(Type type) {
 329             super(Code.typecode(type));
 330         }
 331 
 332         Item load() {
 333             code.emitop0(iaload + typecode);
 334             return stackItem[typecode];
 335         }
 336 
 337         void store() {
 338             code.emitop0(iastore + typecode);
 339         }
 340 
 341         void duplicate() {
 342             code.emitop0(dup2);
 343         }
 344 
 345         void drop() {
 346             code.emitop0(pop2);
 347         }
 348 
 349         void stash(int toscode) {
 350             code.emitop0(dup_x2 + 3 * (Code.width(toscode) - 1));
 351         }
 352 
 353         int width() {
 354             return 2;
 355         }
 356 
 357         public String toString() {
 358             return "indexed(" + ByteCodes.typecodeNames[typecode] + ")";
 359         }
 360     }
 361 
 362     /** An item representing `this' or `super'.
 363      */
 364     class SelfItem extends Item {
 365 
 366         /** Flag which determines whether this item represents `this' or `super'.
 367          */
 368         boolean isSuper;
 369 
 370         SelfItem(boolean isSuper) {
 371             super(OBJECTcode);
 372             this.isSuper = isSuper;
 373         }
 374 
 375         Item load() {
 376             code.emitop0(aload_0);
 377             return stackItem[typecode];
 378         }
 379 
 380         public String toString() {
 381             return isSuper ? "super" : "this";
 382         }
 383     }
 384 
 385     /** An item representing a local variable.
 386      */
 387     class LocalItem extends Item {
 388 
 389         /** The variable's register.
 390          */
 391         int reg;
 392 
 393         /** The variable's type.
 394          */
 395         Type type;
 396 
 397         LocalItem(Type type, int reg) {
 398             super(Code.typecode(type));
 399             Assert.check(reg >= 0);
 400             this.type = type;
 401             this.reg = reg;
 402         }
 403 
 404         Item load() {
 405             if (reg <= 3)
 406                 code.emitop0(iload_0 + Code.truncate(typecode) * 4 + reg);
 407             else
 408                 code.emitop1w(iload + Code.truncate(typecode), reg);
 409             return stackItem[typecode];
 410         }
 411 
 412         void store() {
 413             if (reg <= 3)
 414                 code.emitop0(istore_0 + Code.truncate(typecode) * 4 + reg);
 415             else
 416                 code.emitop1w(istore + Code.truncate(typecode), reg);
 417             code.setDefined(reg);
 418         }
 419 
 420         void incr(int x) {
 421             if (typecode == INTcode && x >= -32768 && x <= 32767) {
 422                 code.emitop1w(iinc, reg, x);
 423             } else {
 424                 load();
 425                 if (x >= 0) {
 426                     makeImmediateItem(syms.intType, x).load();
 427                     code.emitop0(iadd);
 428                 } else {
 429                     makeImmediateItem(syms.intType, -x).load();
 430                     code.emitop0(isub);
 431                 }
 432                 makeStackItem(syms.intType).coerce(typecode);
 433                 store();
 434             }
 435         }
 436 
 437         public String toString() {
 438             return "localItem(type=" + type + "; reg=" + reg + ")";
 439         }
 440     }
 441 
 442     /** An item representing a static variable or method.
 443      */
 444     class StaticItem extends Item {
 445 
 446         /** The represented symbol.
 447          */
 448         Symbol member;
 449 
 450         StaticItem(Symbol member) {
 451             super(Code.typecode(member.erasure(types)));
 452             this.member = member;
 453         }
 454 
 455         Item load() {
 456             code.emitop2(getstatic, pool.put(member));
 457             return stackItem[typecode];
 458         }
 459 
 460         void store() {
 461             code.emitop2(putstatic, pool.put(member));
 462         }
 463 
 464         Item invoke() {
 465             MethodType mtype = (MethodType)member.erasure(types);
 466             int rescode = Code.typecode(mtype.restype);
 467             code.emitInvokestatic(pool.put(member), mtype);
 468             return stackItem[rescode];
 469         }
 470 
 471         public String toString() {
 472             return "static(" + member + ")";
 473         }
 474     }
 475 
 476     /** An item representing a condy
 477      */
 478     class CondyItem extends Item {
 479         DynamicVariable value;
 480 
 481         CondyItem(DynamicVariable value) {
 482             super(Code.typecode(value.type));
 483             this.value = value;
 484         }
 485 
 486         @Override
 487         public String toString() {
 488             return "condy(" + value + ")";
 489         }
 490 
 491         @Override
 492         Item load() {
 493             int idx = pool.put(value);
 494             if (typecode == LONGcode || typecode == DOUBLEcode) {
 495                 code.emitop2(ldc2w, idx);
 496             } else {
 497                 code.emitLdc(idx);
 498             }
 499             return stackItem[typecode];
 500         }
 501     }
 502 
 503     /** An item representing a dynamic call site.
 504      */
 505     class DynamicItem extends StaticItem {
 506         DynamicItem(Symbol member) {
 507             super(member);
 508         }
 509 
 510         Item load() {
 511             Assert.check(member.kind == Kind.VAR);
 512             Type type = member.erasure(types);
 513             int rescode = Code.typecode(type);
 514             code.emitLdc(pool.put(member));
 515             return stackItem[rescode];
 516         }
 517 
 518         void store() {
 519             assert false;
 520         }
 521 
 522         Item invoke() {
 523             Assert.check(member.kind == Kind.MTH);
 524             MethodType mtype = (MethodType)member.erasure(types);
 525             int rescode = Code.typecode(mtype.restype);
 526             code.emitInvokedynamic(pool.put(member), mtype);
 527             return stackItem[rescode];
 528         }
 529 
 530         public String toString() {
 531             return "dynamic(" + member + ")";
 532         }
 533     }
 534 
 535     /** An item representing an instance variable or method.
 536      */
 537     class MemberItem extends Item {
 538 
 539         /** The represented symbol.
 540          */
 541         Symbol member;
 542 
 543         /** Flag that determines whether or not access is virtual.
 544          */
 545         boolean nonvirtual;
 546 
 547         MemberItem(Symbol member, boolean nonvirtual) {
 548             super(Code.typecode(member.erasure(types)));
 549             this.member = member;
 550             this.nonvirtual = nonvirtual;
 551         }
 552 
 553         Item load() {
 554             code.emitop2(getfield, pool.put(member));
 555             return stackItem[typecode];
 556         }
 557 
 558         void store() {
 559             code.emitop2(putfield, pool.put(member));
 560         }
 561 
 562         Item invoke() {
 563             MethodType mtype = (MethodType)member.externalType(types);
 564             int rescode = Code.typecode(mtype.restype);
 565             if ((member.owner.flags() & Flags.INTERFACE) != 0 && !nonvirtual) {
 566                 code.emitInvokeinterface(pool.put(member), mtype);
 567             } else if (nonvirtual) {
 568                 code.emitInvokespecial(pool.put(member), mtype);
 569             } else {
 570                 code.emitInvokevirtual(pool.put(member), mtype);
 571             }
 572             return stackItem[rescode];
 573         }
 574 
 575         void duplicate() {
 576             stackItem[OBJECTcode].duplicate();
 577         }
 578 
 579         void drop() {
 580             stackItem[OBJECTcode].drop();
 581         }
 582 
 583         void stash(int toscode) {
 584             stackItem[OBJECTcode].stash(toscode);
 585         }
 586 
 587         int width() {
 588             return 1;
 589         }
 590 
 591         public String toString() {
 592             return "member(" + member + (nonvirtual ? " nonvirtual)" : ")");
 593         }
 594     }
 595 
 596     /** An item representing a literal.
 597      */
 598     class ImmediateItem extends Item {
 599 
 600         /** The literal's value.
 601          */
 602         Object value;
 603 
 604         ImmediateItem(Type type, Object value) {
 605             super(Code.typecode(type));
 606             this.value = value;
 607         }
 608 
 609         private void ldc() {
 610             int idx = pool.put(value);
 611             if (typecode == LONGcode || typecode == DOUBLEcode) {
 612                 code.emitop2(ldc2w, idx);
 613             } else {
 614                 code.emitLdc(idx);
 615             }
 616         }
 617 
 618         Item load() {
 619             switch (typecode) {
 620             case INTcode: case BYTEcode: case SHORTcode: case CHARcode:
 621                 int ival = ((Number)value).intValue();
 622                 if (-1 <= ival && ival <= 5)
 623                     code.emitop0(iconst_0 + ival);
 624                 else if (Byte.MIN_VALUE <= ival && ival <= Byte.MAX_VALUE)
 625                     code.emitop1(bipush, ival);
 626                 else if (Short.MIN_VALUE <= ival && ival <= Short.MAX_VALUE)
 627                     code.emitop2(sipush, ival);
 628                 else
 629                     ldc();
 630                 break;
 631             case LONGcode:
 632                 long lval = ((Number)value).longValue();
 633                 if (lval == 0 || lval == 1)
 634                     code.emitop0(lconst_0 + (int)lval);
 635                 else
 636                     ldc();
 637                 break;
 638             case FLOATcode:
 639                 float fval = ((Number)value).floatValue();
 640                 if (isPosZero(fval) || fval == 1.0 || fval == 2.0)
 641                     code.emitop0(fconst_0 + (int)fval);
 642                 else {
 643                     ldc();
 644                 }
 645                 break;
 646             case DOUBLEcode:
 647                 double dval = ((Number)value).doubleValue();
 648                 if (isPosZero(dval) || dval == 1.0)
 649                     code.emitop0(dconst_0 + (int)dval);
 650                 else
 651                     ldc();
 652                 break;
 653             case OBJECTcode:
 654                 ldc();
 655                 break;
 656             default:
 657                 Assert.error();
 658             }
 659             return stackItem[typecode];
 660         }
 661         //where
 662             /** Return true iff float number is positive 0.
 663              */
 664             private boolean isPosZero(float x) {
 665                 return x == 0.0f && 1.0f / x > 0.0f;
 666             }
 667             /** Return true iff double number is positive 0.
 668              */
 669             private boolean isPosZero(double x) {
 670                 return x == 0.0d && 1.0d / x > 0.0d;
 671             }
 672 
 673         CondItem mkCond() {
 674             int ival = ((Number)value).intValue();
 675             return makeCondItem(ival != 0 ? goto_ : dontgoto);
 676         }
 677 
 678         Item coerce(int targetcode) {
 679             if (typecode == targetcode) {
 680                 return this;
 681             } else {
 682                 switch (targetcode) {
 683                 case INTcode:
 684                     if (Code.truncate(typecode) == INTcode)
 685                         return this;
 686                     else
 687                         return new ImmediateItem(
 688                             syms.intType,
 689                             ((Number)value).intValue());
 690                 case LONGcode:
 691                     return new ImmediateItem(
 692                         syms.longType,
 693                         ((Number)value).longValue());
 694                 case FLOATcode:
 695                     return new ImmediateItem(
 696                         syms.floatType,
 697                         ((Number)value).floatValue());
 698                 case DOUBLEcode:
 699                     return new ImmediateItem(
 700                         syms.doubleType,
 701                         ((Number)value).doubleValue());
 702                 case BYTEcode:
 703                     return new ImmediateItem(
 704                         syms.byteType,
 705                         (int)(byte)((Number)value).intValue());
 706                 case CHARcode:
 707                     return new ImmediateItem(
 708                         syms.charType,
 709                         (int)(char)((Number)value).intValue());
 710                 case SHORTcode:
 711                     return new ImmediateItem(
 712                         syms.shortType,
 713                         (int)(short)((Number)value).intValue());
 714                 default:
 715                     return super.coerce(targetcode);
 716                 }
 717             }
 718         }
 719 
 720         public String toString() {
 721             return "immediate(" + value + ")";
 722         }
 723     }
 724 
 725     /** An item representing an assignment expressions.
 726      */
 727     class AssignItem extends Item {
 728 
 729         /** The item representing the assignment's left hand side.
 730          */
 731         Item lhs;
 732 
 733         AssignItem(Item lhs) {
 734             super(lhs.typecode);
 735             this.lhs = lhs;
 736         }
 737 
 738         Item load() {
 739             lhs.stash(typecode);
 740             lhs.store();
 741             return stackItem[typecode];
 742         }
 743 
 744         void duplicate() {
 745             load().duplicate();
 746         }
 747 
 748         void drop() {
 749             lhs.store();
 750         }
 751 
 752         void stash(int toscode) {
 753             Assert.error();
 754         }
 755 
 756         int width() {
 757             return lhs.width() + Code.width(typecode);
 758         }
 759 
 760         public String toString() {
 761             return "assign(lhs = " + lhs + ")";
 762         }
 763     }
 764 
 765     /** An item representing a conditional or unconditional jump.
 766      */
 767     class CondItem extends Item {
 768 
 769         /** A chain encomassing all jumps that can be taken
 770          *  if the condition evaluates to true.
 771          */
 772         Chain trueJumps;
 773 
 774         /** A chain encomassing all jumps that can be taken
 775          *  if the condition evaluates to false.
 776          */
 777         Chain falseJumps;
 778 
 779         /** The jump's opcode.
 780          */
 781         int opcode;
 782 
 783         /*
 784          *  An abstract syntax tree of this item. It is needed
 785          *  for branch entries in 'CharacterRangeTable' attribute.
 786          */
 787         JCTree tree;
 788 
 789         CondItem(int opcode, Chain truejumps, Chain falsejumps) {
 790             super(BYTEcode);
 791             this.opcode = opcode;
 792             this.trueJumps = truejumps;
 793             this.falseJumps = falsejumps;
 794         }
 795 
 796         Item load() {
 797             Chain trueChain = null;
 798             Chain falseChain = jumpFalse();
 799             if (!isFalse()) {
 800                 code.resolve(trueJumps);
 801                 code.emitop0(iconst_1);
 802                 trueChain = code.branch(goto_);
 803             }
 804             if (falseChain != null) {
 805                 code.resolve(falseChain);
 806                 code.emitop0(iconst_0);
 807             }
 808             code.resolve(trueChain);
 809             return stackItem[typecode];
 810         }
 811 
 812         void duplicate() {
 813             load().duplicate();
 814         }
 815 
 816         void drop() {
 817             load().drop();
 818         }
 819 
 820         void stash(int toscode) {
 821             Assert.error();
 822         }
 823 
 824         CondItem mkCond() {
 825             return this;
 826         }
 827 
 828         Chain jumpTrue() {
 829             if (tree == null) return Code.mergeChains(trueJumps, code.branch(opcode));
 830             // we should proceed further in -Xjcov mode only
 831             int startpc = code.curCP();
 832             Chain c = Code.mergeChains(trueJumps, code.branch(opcode));
 833             code.crt.put(tree, CRTable.CRT_BRANCH_TRUE, startpc, code.curCP());
 834             return c;
 835         }
 836 
 837         Chain jumpFalse() {
 838             if (tree == null) return Code.mergeChains(falseJumps, code.branch(Code.negate(opcode)));
 839             // we should proceed further in -Xjcov mode only
 840             int startpc = code.curCP();
 841             Chain c = Code.mergeChains(falseJumps, code.branch(Code.negate(opcode)));
 842             code.crt.put(tree, CRTable.CRT_BRANCH_FALSE, startpc, code.curCP());
 843             return c;
 844         }
 845 
 846         CondItem negate() {
 847             CondItem c = new CondItem(Code.negate(opcode), falseJumps, trueJumps);
 848             c.tree = tree;
 849             return c;
 850         }
 851 
 852         int width() {
 853             // a CondItem doesn't have a size on the stack per se.
 854             throw new AssertionError();
 855         }
 856 
 857         boolean isTrue() {
 858             return falseJumps == null && opcode == goto_;
 859         }
 860 
 861         boolean isFalse() {
 862             return trueJumps == null && opcode == dontgoto;
 863         }
 864 
 865         public String toString() {
 866             return "cond(" + Code.mnem(opcode) + ")";
 867         }
 868     }
 869 }