src/share/classes/com/sun/tools/javac/jvm/Items.java

Tue, 25 Sep 2012 11:53:18 +0100

author
mcimadamore
date
Tue, 25 Sep 2012 11:53:18 +0100
changeset 1336
26d93df3905a
parent 820
2d5aff89aaa3
child 1393
d7d932236fee
permissions
-rw-r--r--

7194586: Add back-end support for invokedynamic
Summary: Add support for invokedynamic bytecode instruction; includes suppot for generation of all related classfile attributes
Reviewed-by: jjg

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

mercurial