📄 items.java
字号:
/* * Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Sun designates this * particular file as subject to the "Classpath" exception as provided * by Sun in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */package com.sun.tools.javac.jvm;import com.sun.tools.javac.util.*;import com.sun.tools.javac.code.*;import com.sun.tools.javac.code.Symbol.*;import com.sun.tools.javac.code.Type.*;import com.sun.tools.javac.jvm.Code.*;import com.sun.tools.javac.tree.JCTree;import static com.sun.tools.javac.code.TypeTags.*;import static com.sun.tools.javac.jvm.ByteCodes.*;/** A helper class for code generation. Items are objects * that stand for addressable entities in the bytecode. Each item * supports a fixed protocol for loading the item on the stack, storing * into it, converting it into a jump condition, and several others. * There are many individual forms of items, such as local, static, * indexed, or instance variables, values on the top of stack, the * special values this or super, etc. Individual items are represented as * inner classes in class Items. * * <p><b>This is NOT part of any API supported by Sun Microsystems. If * you write code that depends on this, you do so at your own risk. * This code and its internal interfaces are subject to change or * deletion without notice.</b> */public class Items { /** The current constant pool. */ Pool pool; /** The current code buffer. */ Code code; /** The current symbol table. */ Symtab syms; /** Type utilities. */ Types types; /** Items that exist only once (flyweight pattern). */ private final Item voidItem; private final Item thisItem; private final Item superItem; private final Item[] stackItem = new Item[TypeCodeCount]; public Items(Pool pool, Code code, Symtab syms, Types types) { this.code = code; this.pool = pool; this.types = types; voidItem = new Item(VOIDcode) { public String toString() { return "void"; } }; thisItem = new SelfItem(false); superItem = new SelfItem(true); for (int i = 0; i < VOIDcode; i++) stackItem[i] = new StackItem(i); stackItem[VOIDcode] = voidItem; this.syms = syms; } /** Make a void item */ Item makeVoidItem() { return voidItem; } /** Make an item representing `this'. */ Item makeThisItem() { return thisItem; } /** Make an item representing `super'. */ Item makeSuperItem() { return superItem; } /** Make an item representing a value on stack. * @param type The value's type. */ Item makeStackItem(Type type) { return stackItem[Code.typecode(type)]; } /** Make an item representing an indexed expression. * @param type The expression's type. */ Item makeIndexedItem(Type type) { return new IndexedItem(type); } /** Make an item representing a local variable. * @param v The represented variable. */ LocalItem makeLocalItem(VarSymbol v) { return new LocalItem(v.erasure(types), v.adr); } /** Make an item representing a local anonymous variable. * @param type The represented variable's type. * @param reg The represented variable's register. */ private LocalItem makeLocalItem(Type type, int reg) { return new LocalItem(type, reg); } /** Make an item representing a static variable or method. * @param member The represented symbol. */ Item makeStaticItem(Symbol member) { return new StaticItem(member); } /** Make an item representing an instance variable or method. * @param member The represented symbol. * @param nonvirtual Is the reference not virtual? (true for constructors * and private members). */ Item makeMemberItem(Symbol member, boolean nonvirtual) { return new MemberItem(member, nonvirtual); } /** Make an item representing a literal. * @param type The literal's type. * @param value The literal's value. */ Item makeImmediateItem(Type type, Object value) { return new ImmediateItem(type, value); } /** Make an item representing an assignment expression. * @param lhs The item representing the assignment's left hand side. */ Item makeAssignItem(Item lhs) { return new AssignItem(lhs); } /** Make an item representing a conditional or unconditional jump. * @param opcode The jump's opcode. * @param trueJumps A chain encomassing all jumps that can be taken * if the condition evaluates to true. * @param falseJumps A chain encomassing all jumps that can be taken * if the condition evaluates to false. */ CondItem makeCondItem(int opcode, Chain trueJumps, Chain falseJumps) { return new CondItem(opcode, trueJumps, falseJumps); } /** Make an item representing a conditional or unconditional jump. * @param opcode The jump's opcode. */ CondItem makeCondItem(int opcode) { return makeCondItem(opcode, null, null); } /** The base class of all items, which implements default behavior. */ abstract class Item { /** The type code of values represented by this item. */ int typecode; Item(int typecode) { this.typecode = typecode; } /** Generate code to load this item onto stack. */ Item load() { throw new AssertionError(); } /** Generate code to store top of stack into this item. */ void store() { throw new AssertionError("store unsupported: " + this); } /** Generate code to invoke method represented by this item. */ Item invoke() { throw new AssertionError(this); } /** Generate code to use this item twice. */ void duplicate() {} /** Generate code to avoid having to use this item. */ void drop() {} /** Generate code to stash a copy of top of stack - of typecode toscode - * under this item. */ void stash(int toscode) { stackItem[toscode].duplicate(); } /** Generate code to turn item into a testable condition. */ CondItem mkCond() { load(); return makeCondItem(ifne); } /** Generate code to coerce item to given type code. * @param targetcode The type code to coerce to. */ Item coerce(int targetcode) { if (typecode == targetcode) return this; else { load(); int typecode1 = Code.truncate(typecode); int targetcode1 = Code.truncate(targetcode); if (typecode1 != targetcode1) { int offset = targetcode1 > typecode1 ? targetcode1 - 1 : targetcode1; code.emitop0(i2l + typecode1 * 3 + offset); } if (targetcode != targetcode1) { code.emitop0(int2byte + targetcode - BYTEcode); } return stackItem[targetcode]; } } /** Generate code to coerce item to given type. * @param targettype The type to coerce to. */ Item coerce(Type targettype) { return coerce(Code.typecode(targettype)); } /** Return the width of this item on stack as a number of words. */ int width() { return 0; } public abstract String toString(); } /** An item representing a value on stack. */ class StackItem extends Item { StackItem(int typecode) { super(typecode); } Item load() { return this; } void duplicate() { code.emitop0(width() == 2 ? dup2 : dup); } void drop() { code.emitop0(width() == 2 ? pop2 : pop); } void stash(int toscode) { code.emitop0( (width() == 2 ? dup_x2 : dup_x1) + 3 * (Code.width(toscode) - 1)); } int width() { return Code.width(typecode); } public String toString() { return "stack(" + typecodeNames[typecode] + ")"; } } /** An item representing an indexed expression. */ class IndexedItem extends Item { IndexedItem(Type type) { super(Code.typecode(type)); } Item load() { code.emitop0(iaload + typecode); return stackItem[typecode]; } void store() { code.emitop0(iastore + typecode); } void duplicate() { code.emitop0(dup2); } void drop() { code.emitop0(pop2); } void stash(int toscode) { code.emitop0(dup_x2 + 3 * (Code.width(toscode) - 1)); } int width() { return 2; } public String toString() { return "indexed(" + ByteCodes.typecodeNames[typecode] + ")"; } } /** An item representing `this' or `super'. */ class SelfItem extends Item { /** Flag which determines whether this item represents `this' or `super'. */ boolean isSuper; SelfItem(boolean isSuper) { super(OBJECTcode); this.isSuper = isSuper; } Item load() { code.emitop0(aload_0); return stackItem[typecode]; } public String toString() { return isSuper ? "super" : "this"; } } /** An item representing a local variable. */ class LocalItem extends Item { /** The variable's register. */ int reg; /** The variable's type. */ Type type; LocalItem(Type type, int reg) { super(Code.typecode(type)); assert reg >= 0; this.type = type; this.reg = reg; } Item load() { if (reg <= 3) code.emitop0(iload_0 + Code.truncate(typecode) * 4 + reg); else code.emitop1w(iload + Code.truncate(typecode), reg); return stackItem[typecode]; } void store() { if (reg <= 3) code.emitop0(istore_0 + Code.truncate(typecode) * 4 + reg); else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -