1 /*
   2  * Copyright (c) 1999, 2019, 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.Symbol.*;
  30 import com.sun.tools.javac.code.Type.*;
  31 import com.sun.tools.javac.jvm.Code.*;
  32 import com.sun.tools.javac.jvm.PoolConstant.LoadableConstant;
  33 import com.sun.tools.javac.jvm.PoolConstant.LoadableConstant.BasicConstant;
  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 writer.
  56      */
  57     PoolWriter poolWriter;
  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(PoolWriter poolWriter, Code code, Symtab syms, Types types) {
  78         this.code = code;
  79         this.poolWriter = poolWriter;
  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 an assignment expression.
 169      *  @param lhs      The item representing the assignment's left hand side.
 170      */
 171     Item makeAssignItem(Item lhs) {
 172         return new AssignItem(lhs);
 173     }
 174 
 175     /** Make an item representing a conditional or unconditional jump.
 176      *  @param opcode      The jump's opcode.
 177      *  @param trueJumps   A chain encomassing all jumps that can be taken
 178      *                     if the condition evaluates to true.
 179      *  @param falseJumps  A chain encomassing all jumps that can be taken
 180      *                     if the condition evaluates to false.
 181      */
 182     CondItem makeCondItem(int opcode, Chain trueJumps, Chain falseJumps) {
 183         return new CondItem(opcode, trueJumps, falseJumps);
 184     }
 185 
 186     /** Make an item representing a conditional or unconditional jump.
 187      *  @param opcode      The jump's opcode.
 188      */
 189     CondItem makeCondItem(int opcode) {
 190         return makeCondItem(opcode, null, null);
 191     }
 192 
 193     /** The base class of all items, which implements default behavior.
 194      */
 195     abstract class Item {
 196 
 197         /** The type code of values represented by this item.
 198          */
 199         int typecode;
 200 
 201         Item(int typecode) {
 202             this.typecode = typecode;
 203         }
 204 
 205         /** Generate code to load this item onto stack.
 206          */
 207         Item load() {
 208             throw new AssertionError();
 209         }
 210 
 211         /** Generate code to store top of stack into this item.
 212          */
 213         void store() {
 214             throw new AssertionError("store unsupported: " + this);
 215         }
 216 
 217         /** Generate code to invoke method represented by this item.
 218          */
 219         Item invoke() {
 220             throw new AssertionError(this);
 221         }
 222 
 223         /** Generate code to use this item twice.
 224          */
 225         void duplicate() {}
 226 
 227         /** Generate code to avoid having to use this item.
 228          */
 229         void drop() {}
 230 
 231         /** Generate code to stash a copy of top of stack - of typecode toscode -
 232          *  under this item.
 233          */
 234         void stash(int toscode) {
 235             stackItem[toscode].duplicate();
 236         }
 237 
 238         /** Generate code to turn item into a testable condition.
 239          */
 240         CondItem mkCond() {
 241             load();
 242             return makeCondItem(ifne);
 243         }
 244 
 245         /** Generate code to coerce item to given type code.
 246          *  @param targetcode    The type code to coerce to.
 247          */
 248         Item coerce(int targetcode) {
 249             if (typecode == targetcode)
 250                 return this;
 251             else {
 252                 load();
 253                 int typecode1 = Code.truncate(typecode);
 254                 int targetcode1 = Code.truncate(targetcode);
 255                 if (typecode1 != targetcode1) {
 256                     int offset = targetcode1 > typecode1 ? targetcode1 - 1
 257                         : targetcode1;
 258                     code.emitop0(i2l + typecode1 * 3 + offset);
 259                 }
 260                 if (targetcode != targetcode1) {
 261                     code.emitop0(int2byte + targetcode - BYTEcode);
 262                 }
 263                 return stackItem[targetcode];
 264             }
 265         }
 266 
 267         /** Generate code to coerce item to given type.
 268          *  @param targettype    The type to coerce to.
 269          */
 270         Item coerce(Type targettype) {
 271             return coerce(Code.typecode(targettype));
 272         }
 273 
 274         /** Return the width of this item on stack as a number of words.
 275          */
 276         int width() {
 277             return 0;
 278         }
 279 
 280         public abstract String toString();
 281     }
 282 
 283     /** An item representing a value on stack.
 284      */
 285     class StackItem extends Item {
 286 
 287         StackItem(int typecode) {
 288             super(typecode);
 289         }
 290 
 291         Item load() {
 292             return this;
 293         }
 294 
 295         void duplicate() {
 296             code.emitop0(width() == 2 ? dup2 : dup);
 297         }
 298 
 299         void drop() {
 300             code.emitop0(width() == 2 ? pop2 : pop);
 301         }
 302 
 303         void stash(int toscode) {
 304             code.emitop0(
 305                 (width() == 2 ? dup_x2 : dup_x1) + 3 * (Code.width(toscode) - 1));
 306         }
 307 
 308         int width() {
 309             return Code.width(typecode);
 310         }
 311 
 312         public String toString() {
 313             return "stack(" + typecodeNames[typecode] + ")";
 314         }
 315     }
 316 
 317     /** An item representing an indexed expression.
 318      */
 319     class IndexedItem extends Item {
 320 
 321         IndexedItem(Type type) {
 322             super(Code.typecode(type));
 323         }
 324 
 325         Item load() {
 326             code.emitop0(iaload + typecode);
 327             return stackItem[typecode];
 328         }
 329 
 330         void store() {
 331             code.emitop0(iastore + typecode);
 332         }
 333 
 334         void duplicate() {
 335             code.emitop0(dup2);
 336         }
 337 
 338         void drop() {
 339             code.emitop0(pop2);
 340         }
 341 
 342         void stash(int toscode) {
 343             code.emitop0(dup_x2 + 3 * (Code.width(toscode) - 1));
 344         }
 345 
 346         int width() {
 347             return 2;
 348         }
 349 
 350         public String toString() {
 351             return "indexed(" + ByteCodes.typecodeNames[typecode] + ")";
 352         }
 353     }
 354 
 355     /** An item representing `this' or `super'.
 356      */
 357     class SelfItem extends Item {
 358 
 359         /** Flag which determines whether this item represents `this' or `super'.
 360          */
 361         boolean isSuper;
 362 
 363         SelfItem(boolean isSuper) {
 364             super(OBJECTcode);
 365             this.isSuper = isSuper;
 366         }
 367 
 368         Item load() {
 369             code.emitop0(aload_0);
 370             return stackItem[typecode];
 371         }
 372 
 373         public String toString() {
 374             return isSuper ? "super" : "this";
 375         }
 376     }
 377 
 378     /** An item representing a local variable.
 379      */
 380     class LocalItem extends Item {
 381 
 382         /** The variable's register.
 383          */
 384         int reg;
 385 
 386         /** The variable's type.
 387          */
 388         Type type;
 389 
 390         LocalItem(Type type, int reg) {
 391             super(Code.typecode(type));
 392             Assert.check(reg >= 0);
 393             this.type = type;
 394             this.reg = reg;
 395         }
 396 
 397         Item load() {
 398             if (reg <= 3)
 399                 code.emitop0(iload_0 + Code.truncate(typecode) * 4 + reg);
 400             else
 401                 code.emitop1w(iload + Code.truncate(typecode), reg);
 402             return stackItem[typecode];
 403         }
 404 
 405         void store() {
 406             if (reg <= 3)
 407                 code.emitop0(istore_0 + Code.truncate(typecode) * 4 + reg);
 408             else
 409                 code.emitop1w(istore + Code.truncate(typecode), reg);
 410             code.setDefined(reg);
 411         }
 412 
 413         void incr(int x) {
 414             if (typecode == INTcode && x >= -32768 && x <= 32767) {
 415                 code.emitop1w(iinc, reg, x);
 416             } else {
 417                 load();
 418                 if (x >= 0) {
 419                     makeImmediateItem(syms.intType, x).load();
 420                     code.emitop0(iadd);
 421                 } else {
 422                     makeImmediateItem(syms.intType, -x).load();
 423                     code.emitop0(isub);
 424                 }
 425                 makeStackItem(syms.intType).coerce(typecode);
 426                 store();
 427             }
 428         }
 429 
 430         public String toString() {
 431             return "localItem(type=" + type + "; reg=" + reg + ")";
 432         }
 433     }
 434 
 435     /** An item representing a static variable or method.
 436      */
 437     class StaticItem extends Item {
 438 
 439         /** The represented symbol.
 440          */
 441         Symbol member;
 442 
 443         StaticItem(Symbol member) {
 444             super(Code.typecode(member.erasure(types)));
 445             this.member = member;
 446         }
 447 
 448         Item load() {
 449             code.emitop2(getstatic, member, PoolWriter::putMember);
 450             return stackItem[typecode];
 451         }
 452 
 453         void store() {
 454             code.emitop2(putstatic, member, PoolWriter::putMember);
 455         }
 456 
 457         Item invoke() {
 458             MethodType mtype = (MethodType)member.erasure(types);
 459             int rescode = Code.typecode(mtype.restype);
 460             code.emitInvokestatic(member, mtype);
 461             return stackItem[rescode];
 462         }
 463 
 464         public String toString() {
 465             return "static(" + member + ")";
 466         }
 467     }
 468 
 469     /** An item representing a dynamic call site.
 470      */
 471     class DynamicItem extends StaticItem {
 472         DynamicItem(Symbol member) {
 473             super(member);
 474         }
 475 
 476         Item load() {
 477             Assert.check(member.kind == Kinds.Kind.VAR);
 478             Type type = member.erasure(types);
 479             int rescode = Code.typecode(type);
 480             code.emitLdc((DynamicVarSymbol)member);
 481             return stackItem[rescode];
 482         }
 483 
 484         void store() { Assert.error("this method shouldn't be invoked"); }
 485 
 486         Item invoke() {
 487             Assert.check(member.kind == Kinds.Kind.MTH);
 488             MethodType mtype = (MethodType)member.erasure(types);
 489             int rescode = Code.typecode(mtype.restype);
 490             code.emitInvokedynamic((DynamicMethodSymbol)member, mtype);
 491             return stackItem[rescode];
 492         }
 493 
 494         public String toString() {
 495             return "dynamic(" + member + ")";
 496         }
 497     }
 498 
 499     /** An item representing an instance variable or method.
 500      */
 501     class MemberItem extends Item {
 502 
 503         /** The represented symbol.
 504          */
 505         Symbol member;
 506 
 507         /** Flag that determines whether or not access is virtual.
 508          */
 509         boolean nonvirtual;
 510 
 511         MemberItem(Symbol member, boolean nonvirtual) {
 512             super(Code.typecode(member.erasure(types)));
 513             this.member = member;
 514             this.nonvirtual = nonvirtual;
 515         }
 516 
 517         Item load() {
 518             code.emitop2(getfield, member, PoolWriter::putMember);
 519             return stackItem[typecode];
 520         }
 521 
 522         void store() {
 523             code.emitop2(putfield, member, PoolWriter::putMember);
 524         }
 525 
 526         Item invoke() {
 527             MethodType mtype = (MethodType)member.externalType(types);
 528             int rescode = Code.typecode(mtype.restype);
 529             if ((member.owner.flags() & Flags.INTERFACE) != 0 && !nonvirtual) {
 530                 code.emitInvokeinterface(member, mtype);
 531             } else if (nonvirtual) {
 532                 code.emitInvokespecial(member, mtype);
 533             } else {
 534                 code.emitInvokevirtual(member, mtype);
 535             }
 536             return stackItem[rescode];
 537         }
 538 
 539         void duplicate() {
 540             stackItem[OBJECTcode].duplicate();
 541         }
 542 
 543         void drop() {
 544             stackItem[OBJECTcode].drop();
 545         }
 546 
 547         void stash(int toscode) {
 548             stackItem[OBJECTcode].stash(toscode);
 549         }
 550 
 551         int width() {
 552             return 1;
 553         }
 554 
 555         public String toString() {
 556             return "member(" + member + (nonvirtual ? " nonvirtual)" : ")");
 557         }
 558     }
 559 
 560     /** An item representing a literal.
 561      */
 562     class ImmediateItem extends Item {
 563 
 564         /** The literal's value.
 565          */
 566         final LoadableConstant value;
 567 
 568         ImmediateItem(Type type, Object value) {
 569             super(Code.typecode(type));
 570             switch (typecode) {
 571                 case BYTEcode:
 572                 case SHORTcode:
 573                 case CHARcode:
 574                 case INTcode:
 575                     this.value = LoadableConstant.Int((int)value);
 576                     break;
 577                 case LONGcode:
 578                     this.value = LoadableConstant.Long((long)value);
 579                     break;
 580                 case FLOATcode:
 581                     this.value = LoadableConstant.Float((float)value);
 582                     break;
 583                 case DOUBLEcode:
 584                     this.value = LoadableConstant.Double((double)value);
 585                     break;
 586                 case OBJECTcode:
 587                     this.value = LoadableConstant.String((String)value);
 588                     break;
 589                 default:
 590                     throw new UnsupportedOperationException("unsupported tag: " + typecode);
 591             }
 592         }
 593 
 594         private void ldc() {
 595             if (typecode == LONGcode || typecode == DOUBLEcode) {
 596                 code.emitop2(ldc2w, value, PoolWriter::putConstant);
 597             } else {
 598                 code.emitLdc(value);
 599             }
 600         }
 601 
 602         private Number numericValue() {
 603             return (Number)((BasicConstant)value).data;
 604         }
 605 
 606         Item load() {
 607             switch (typecode) {
 608             case INTcode: case BYTEcode: case SHORTcode: case CHARcode:
 609                 int ival = numericValue().intValue();
 610                 if (-1 <= ival && ival <= 5)
 611                     code.emitop0(iconst_0 + ival);
 612                 else if (Byte.MIN_VALUE <= ival && ival <= Byte.MAX_VALUE)
 613                     code.emitop1(bipush, ival);
 614                 else if (Short.MIN_VALUE <= ival && ival <= Short.MAX_VALUE)
 615                     code.emitop2(sipush, ival);
 616                 else
 617                     ldc();
 618                 break;
 619             case LONGcode:
 620                 long lval = numericValue().longValue();
 621                 if (lval == 0 || lval == 1)
 622                     code.emitop0(lconst_0 + (int)lval);
 623                 else
 624                     ldc();
 625                 break;
 626             case FLOATcode:
 627                 float fval = numericValue().floatValue();
 628                 if (isPosZero(fval) || fval == 1.0 || fval == 2.0)
 629                     code.emitop0(fconst_0 + (int)fval);
 630                 else {
 631                     ldc();
 632                 }
 633                 break;
 634             case DOUBLEcode:
 635                 double dval = numericValue().doubleValue();
 636                 if (isPosZero(dval) || dval == 1.0)
 637                     code.emitop0(dconst_0 + (int)dval);
 638                 else
 639                     ldc();
 640                 break;
 641             case OBJECTcode:
 642                 ldc();
 643                 break;
 644             default:
 645                 Assert.error();
 646             }
 647             return stackItem[typecode];
 648         }
 649         //where
 650             /** Return true iff float number is positive 0.
 651              */
 652             private boolean isPosZero(float x) {
 653                 return x == 0.0f && 1.0f / x > 0.0f;
 654             }
 655             /** Return true iff double number is positive 0.
 656              */
 657             private boolean isPosZero(double x) {
 658                 return x == 0.0d && 1.0d / x > 0.0d;
 659             }
 660 
 661         CondItem mkCond() {
 662             int ival = numericValue().intValue();
 663             return makeCondItem(ival != 0 ? goto_ : dontgoto);
 664         }
 665 
 666         Item coerce(int targetcode) {
 667             if (typecode == targetcode) {
 668                 return this;
 669             } else {
 670                 switch (targetcode) {
 671                 case INTcode:
 672                     if (Code.truncate(typecode) == INTcode)
 673                         return this;
 674                     else
 675                         return new ImmediateItem(
 676                             syms.intType,
 677                             numericValue().intValue());
 678                 case LONGcode:
 679                     return new ImmediateItem(
 680                         syms.longType,
 681                             numericValue().longValue());
 682                 case FLOATcode:
 683                     return new ImmediateItem(
 684                         syms.floatType,
 685                         numericValue().floatValue());
 686                 case DOUBLEcode:
 687                     return new ImmediateItem(
 688                         syms.doubleType,
 689                         numericValue().doubleValue());
 690                 case BYTEcode:
 691                     return new ImmediateItem(
 692                         syms.byteType,
 693                         (int)(byte)numericValue().intValue());
 694                 case CHARcode:
 695                     return new ImmediateItem(
 696                         syms.charType,
 697                         (int)(char)numericValue().intValue());
 698                 case SHORTcode:
 699                     return new ImmediateItem(
 700                         syms.shortType,
 701                         (int)(short)numericValue().intValue());
 702                 default:
 703                     return super.coerce(targetcode);
 704                 }
 705             }
 706         }
 707 
 708         public String toString() {
 709             return "immediate(" + value + ")";
 710         }
 711     }
 712 
 713     /** An item representing an assignment expressions.
 714      */
 715     class AssignItem extends Item {
 716 
 717         /** The item representing the assignment's left hand side.
 718          */
 719         Item lhs;
 720 
 721         AssignItem(Item lhs) {
 722             super(lhs.typecode);
 723             this.lhs = lhs;
 724         }
 725 
 726         Item load() {
 727             lhs.stash(typecode);
 728             lhs.store();
 729             return stackItem[typecode];
 730         }
 731 
 732         void duplicate() {
 733             load().duplicate();
 734         }
 735 
 736         void drop() {
 737             lhs.store();
 738         }
 739 
 740         void stash(int toscode) {
 741             Assert.error();
 742         }
 743 
 744         int width() {
 745             return lhs.width() + Code.width(typecode);
 746         }
 747 
 748         public String toString() {
 749             return "assign(lhs = " + lhs + ")";
 750         }
 751     }
 752 
 753     /** An item representing a conditional or unconditional jump.
 754      */
 755     class CondItem extends Item {
 756 
 757         /** A chain encomassing all jumps that can be taken
 758          *  if the condition evaluates to true.
 759          */
 760         Chain trueJumps;
 761 
 762         /** A chain encomassing all jumps that can be taken
 763          *  if the condition evaluates to false.
 764          */
 765         Chain falseJumps;
 766 
 767         /** The jump's opcode.
 768          */
 769         int opcode;
 770 
 771         /*
 772          *  An abstract syntax tree of this item. It is needed
 773          *  for branch entries in 'CharacterRangeTable' attribute.
 774          */
 775         JCTree tree;
 776 
 777         CondItem(int opcode, Chain truejumps, Chain falsejumps) {
 778             super(BYTEcode);
 779             this.opcode = opcode;
 780             this.trueJumps = truejumps;
 781             this.falseJumps = falsejumps;
 782         }
 783 
 784         Item load() {
 785             Chain trueChain = null;
 786             Chain falseChain = jumpFalse();
 787             if (!isFalse()) {
 788                 code.resolve(trueJumps);
 789                 code.emitop0(iconst_1);
 790                 trueChain = code.branch(goto_);
 791             }
 792             if (falseChain != null) {
 793                 code.resolve(falseChain);
 794                 code.emitop0(iconst_0);
 795             }
 796             code.resolve(trueChain);
 797             return stackItem[typecode];
 798         }
 799 
 800         void duplicate() {
 801             load().duplicate();
 802         }
 803 
 804         void drop() {
 805             load().drop();
 806         }
 807 
 808         void stash(int toscode) {
 809             Assert.error();
 810         }
 811 
 812         CondItem mkCond() {
 813             return this;
 814         }
 815 
 816         Chain jumpTrue() {
 817             if (tree == null) return Code.mergeChains(trueJumps, code.branch(opcode));
 818             // we should proceed further in -Xjcov mode only
 819             int startpc = code.curCP();
 820             Chain c = Code.mergeChains(trueJumps, code.branch(opcode));
 821             code.crt.put(tree, CRTable.CRT_BRANCH_TRUE, startpc, code.curCP());
 822             return c;
 823         }
 824 
 825         Chain jumpFalse() {
 826             if (tree == null) return Code.mergeChains(falseJumps, code.branch(Code.negate(opcode)));
 827             // we should proceed further in -Xjcov mode only
 828             int startpc = code.curCP();
 829             Chain c = Code.mergeChains(falseJumps, code.branch(Code.negate(opcode)));
 830             code.crt.put(tree, CRTable.CRT_BRANCH_FALSE, startpc, code.curCP());
 831             return c;
 832         }
 833 
 834         CondItem negate() {
 835             CondItem c = new CondItem(Code.negate(opcode), falseJumps, trueJumps);
 836             c.tree = tree;
 837             return c;
 838         }
 839 
 840         int width() {
 841             // a CondItem doesn't have a size on the stack per se.
 842             throw new AssertionError();
 843         }
 844 
 845         boolean isTrue() {
 846             return falseJumps == null && opcode == goto_;
 847         }
 848 
 849         boolean isFalse() {
 850             return trueJumps == null && opcode == dontgoto;
 851         }
 852 
 853         public String toString() {
 854             return "cond(" + Code.mnem(opcode) + ")";
 855         }
 856     }
 857 }