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

Thu, 12 Oct 2017 19:50:01 +0800

author
aoqi
date
Thu, 12 Oct 2017 19:50:01 +0800
changeset 2702
9ca8d8713094
parent 2525
2eb010b6cb22
permissions
-rw-r--r--

merge

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

mercurial