📄 items.java
字号:
/**
* @(#)Items.java 1.22 03/01/23
*
* Copyright 2003 Sun Microsystems, Inc. All rights reserved.
* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
package com.sun.tools.javac.v8.comp;
import com.sun.tools.javac.v8.util.*;
import com.sun.tools.javac.v8.code.*;
import com.sun.tools.javac.v8.code.Symbol.*;
import com.sun.tools.javac.v8.code.Type.*;
import com.sun.tools.javac.v8.code.Code.*;
import com.sun.tools.javac.v8.tree.Tree;
/**
* 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.
*/
public class Items implements ByteCodes, TypeTags {
/**
* The current constant pool.
*/
Pool pool;
/**
* The current code buffer.
*/
Code code;
/**
* The current symbol table.
*/
Symtab syms;
/**
* 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) {
super();
this.code = code;
this.pool = pool;
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.
*/
Item makeLocalItem(VarSymbol v) {
return new LocalItem(v.erasure(), v.adr);
}
/**
* Make an item representing a local anonymous variable.
* @param type The represented variable's type.
* @param reg The represented variable's register.
*/
Item 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 t 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) {
super();
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.
*/
Item store() {
throw new AssertionError("store unsupported: " + this);
}
/**
* Generate code to invoke method represented by this item.
*/
Item invoke() {
throw new AssertionError(this.toString());
}
/**
* 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.emitop(i2l + typecode1 * 3 + offset);
}
if (targetcode != targetcode1) {
code.emitop(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.emitop(width() == 2 ? dup2 : dup);
}
void drop() {
code.emitop(width() == 2 ? pop2 : pop);
}
void stash(int toscode) {
code.emitop((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.emitop(iaload + typecode);
return stackItem[typecode];
}
Item store() {
code.emitop(iastore + typecode);
return voidItem;
}
void duplicate() {
code.emitop(dup2);
}
void drop() {
code.emitop(pop2);
}
void stash(int toscode) {
code.emitop(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.emitop(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.emitop(iload_0 + Code.truncate(typecode) * 4 + reg);
else
code.emitop1w(iload + Code.truncate(typecode), reg);
return stackItem[typecode];
}
Item store() {
if (reg <= 3)
code.emitop(istore_0 + Code.truncate(typecode) * 4 + reg);
else
code.emitop1w(istore + Code.truncate(typecode), reg);
code.setDefined(reg);
return voidItem;
}
void incr(int x) {
if (typecode == INTcode) {
code.emitop1w(iinc, reg);
if (reg > 255)
code.emit2(x);
else
code.emit1(x);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -