Here are the examples of the java api com.feilong.lib.javassist.CtClass taken from open source projects. By voting up you can indicate which examples are most useful and appropriate.
167 Examples
19
Source : ScopedClassPool.java
with Apache License 2.0
from ifeilong
with Apache License 2.0
from ifeilong
/**
* Convert a javreplacedist clreplaced to a java clreplaced
*
* @param ct
* the javreplacedist clreplaced
* @param loader
* the loader
* @throws CannotCompileException
* for any error
*/
@Override
public Clreplaced<?> toClreplaced(CtClreplaced ct, ClreplacedLoader loader, ProtectionDomain domain) throws CannotCompileException {
// We need to preplaced up the clreplacedloader stored in this pool, as the
// default implementation uses the Thread context cl.
// In the case of JSP's in Tomcat,
// org.apache.jasper.servlet.JasperLoader will be stored here, while
// it's parent
// org.jboss.web.tomcat.tc5.WebCtxLoader$ENCLoader is used as the Thread
// context cl. The invocation clreplaced needs to
// be generated in the JasperLoader clreplacedloader since in the case of
// method invocations, the package name will be
// the same as for the clreplaced generated from the jsp, i.e.
// org.apache.jsp. For clreplacedes belonging to org.apache.jsp,
// JasperLoader does NOT delegate to its parent if it cannot find them.
lockInCache(ct);
return super.toClreplaced(ct, getClreplacedLoader0(), domain);
}
19
Source : ScopedClassPool.java
with Apache License 2.0
from ifeilong
with Apache License 2.0
from ifeilong
/**
* Whether the clreplaced is cached in this pooled
*
* @param clreplacedname
* the clreplaced name
* @return the cached clreplaced
*/
protected CtClreplaced getCachedLocally(String clreplacedname) {
CtClreplaced cached = (CtClreplaced) clreplacedes.get(clreplacedname);
if (cached != null) {
return cached;
}
synchronized (softcache) {
return softcache.get(clreplacedname);
}
}
19
Source : ScopedClassPool.java
with Apache License 2.0
from ifeilong
with Apache License 2.0
from ifeilong
/**
* Lock a clreplaced into the cache
*
* @param c
* the clreplaced
*/
public void lockInCache(CtClreplaced c) {
super.cacheCtClreplaced(c.getName(), c, false);
}
19
Source : ScopedClassPool.java
with Apache License 2.0
from ifeilong
with Apache License 2.0
from ifeilong
/**
* Get the cached clreplaced
*
* @param clreplacedname
* the clreplaced name
* @return the clreplaced
*/
@Override
protected CtClreplaced getCached(String clreplacedname) {
CtClreplaced clazz = getCachedLocally(clreplacedname);
if (clazz == null) {
boolean isLocal = false;
ClreplacedLoader dcl = getClreplacedLoader0();
if (dcl != null) {
final int lastIndex = clreplacedname.lastIndexOf('$');
String clreplacedResourceName = null;
if (lastIndex < 0) {
clreplacedResourceName = clreplacedname.replaceAll("[\\.]", "/") + ".clreplaced";
} else {
clreplacedResourceName = clreplacedname.substring(0, lastIndex).replaceAll("[\\.]", "/") + clreplacedname.substring(lastIndex) + ".clreplaced";
}
isLocal = dcl.getResource(clreplacedResourceName) != null;
}
if (!isLocal) {
Map<ClreplacedLoader, ScopedClreplacedPool> registeredCLs = repository.getRegisteredCLs();
synchronized (registeredCLs) {
for (ScopedClreplacedPool pool : registeredCLs.values()) {
if (pool.isUnloadedClreplacedLoader()) {
repository.unregisterClreplacedLoader(pool.getClreplacedLoader());
continue;
}
clazz = pool.getCachedLocally(clreplacedname);
if (clazz != null) {
return clazz;
}
}
}
}
}
// *NOTE* NEED TO TEST WHEN SUPERCLreplaced IS IN ANOTHER UCL!!!!!!
return clazz;
}
19
Source : ScopedClassPool.java
with Apache License 2.0
from ifeilong
with Apache License 2.0
from ifeilong
/**
* Get any local copy of the clreplaced
*
* @param clreplacedname
* the clreplaced name
* @return the clreplaced
* @throws NotFoundException
* when the clreplaced is not found
*/
public synchronized CtClreplaced getLocally(String clreplacedname) throws NotFoundException {
softcache.remove(clreplacedname);
CtClreplaced clazz = (CtClreplaced) clreplacedes.get(clreplacedname);
if (clazz == null) {
clazz = createCtClreplaced(clreplacedname, true);
if (clazz == null) {
throw new NotFoundException(clreplacedname);
}
super.cacheCtClreplaced(clreplacedname, clazz, false);
}
return clazz;
}
19
Source : ExprEditor.java
with Apache License 2.0
from ifeilong
with Apache License 2.0
from ifeilong
/**
* Visits each bytecode in the given range.
*/
boolean doit(CtClreplaced clazz, MethodInfo minfo, LoopContext context, CodeIterator iterator, int endPos) throws CannotCompileException {
boolean edited = false;
while (iterator.hasNext() && iterator.lookAhead() < endPos) {
int size = iterator.getCodeLength();
if (loopBody(iterator, clazz, minfo, context)) {
edited = true;
int size2 = iterator.getCodeLength();
if (size != size2) {
endPos += size2 - size;
}
}
}
return edited;
}
19
Source : Expr.java
with Apache License 2.0
from ifeilong
with Apache License 2.0
from ifeilong
/**
* Expression.
*/
public abstract clreplaced Expr implements Opcode {
int currentPos;
CodeIterator iterator;
CtClreplaced thisClreplaced;
MethodInfo thisMethod;
boolean edited;
int maxLocals, maxStack;
static final String javaLangObject = "java.lang.Object";
/**
* Undoreplacedented constructor. Do not use; internal-use only.
*/
protected Expr(int pos, CodeIterator i, CtClreplaced declaring, MethodInfo m) {
currentPos = pos;
iterator = i;
thisClreplaced = declaring;
thisMethod = m;
}
/**
* Returns the clreplaced that declares the method enclosing
* this expression.
*
* @since 3.7
*/
public CtClreplaced getEnclosingClreplaced() {
return thisClreplaced;
}
protected final ConstPool getConstPool() {
return thisMethod.getConstPool();
}
protected final boolean edited() {
return edited;
}
protected final int locals() {
return maxLocals;
}
protected final int stack() {
return maxStack;
}
/**
* Returns true if this method is static.
*/
protected final boolean withinStatic() {
return (thisMethod.getAccessFlags() & AccessFlag.STATIC) != 0;
}
/**
* Returns the constructor or method containing the expression.
*/
public CtBehavior where() {
MethodInfo mi = thisMethod;
CtBehavior[] cb = thisClreplaced.getDeclaredBehaviors();
for (int i = cb.length - 1; i >= 0; --i) {
if (cb[i].getMethodInfo2() == mi) {
return cb[i];
}
}
CtConstructor init = thisClreplaced.getClreplacedInitializer();
if (init != null && init.getMethodInfo2() == mi) {
return init;
}
/*
* getDeclaredBehaviors() returns a list of methods/constructors.
* Although the list is cached in a CtClreplaced object, it might be
* recreated for some reason. Thus, the member name and the signature
* must be also checked.
*/
for (int i = cb.length - 1; i >= 0; --i) {
if (thisMethod.getName().equals(cb[i].getMethodInfo2().getName()) && thisMethod.getDescriptor().equals(cb[i].getMethodInfo2().getDescriptor())) {
return cb[i];
}
}
throw new RuntimeException("fatal: not found");
}
/**
* Returns the list of exceptions that the expression may throw. This list
* includes both the exceptions that the try-catch statements including the
* expression can catch and the exceptions that the throws declaration
* allows the method to throw.
*/
public CtClreplaced[] mayThrow() {
ClreplacedPool pool = thisClreplaced.getClreplacedPool();
ConstPool cp = thisMethod.getConstPool();
List<CtClreplaced> list = new LinkedList<>();
try {
CodeAttribute ca = thisMethod.getCodeAttribute();
ExceptionTable et = ca.getExceptionTable();
int pos = currentPos;
int n = et.size();
for (int i = 0; i < n; ++i) {
if (et.startPc(i) <= pos && pos < et.endPc(i)) {
int t = et.catchType(i);
if (t > 0) {
try {
addClreplaced(list, pool.get(cp.getClreplacedInfo(t)));
} catch (NotFoundException e) {
}
}
}
}
} catch (NullPointerException e) {
}
ExceptionsAttribute ea = thisMethod.getExceptionsAttribute();
if (ea != null) {
String[] exceptions = ea.getExceptions();
if (exceptions != null) {
int n = exceptions.length;
for (int i = 0; i < n; ++i) {
try {
addClreplaced(list, pool.get(exceptions[i]));
} catch (NotFoundException e) {
}
}
}
}
return list.toArray(new CtClreplaced[list.size()]);
}
private static void addClreplaced(List<CtClreplaced> list, CtClreplaced c) {
if (list.contains(c)) {
return;
}
list.add(c);
}
/**
* Returns the index of the bytecode corresponding to the expression. It is
* the index into the byte array containing the Java bytecode that
* implements the method.
*/
public int indexOfBytecode() {
return currentPos;
}
/**
* Returns the line number of the source line containing the expression.
*
* @return -1 if this information is not available.
*/
public int getLineNumber() {
return thisMethod.getLineNumber(currentPos);
}
/**
* Returns the source file containing the expression.
*
* @return null if this information is not available.
*/
public String getFileName() {
ClreplacedFile cf = thisClreplaced.getClreplacedFile2();
if (cf == null) {
return null;
}
return cf.getSourceFile();
}
static final boolean checkResultValue(CtClreplaced retType, String prog) throws CannotCompileException {
/*
* Is $_ included in the source code?
*/
boolean hasIt = (prog.indexOf(Javac.resultVarName) >= 0);
if (!hasIt && retType != CtClreplaced.voidType) {
throw new CannotCompileException("the resulting value is not stored in " + Javac.resultVarName);
}
return hasIt;
}
/*
* If isStaticCall is true, null is replacedigned to $0. So $0 must be declared
* by calling Javac.recordParams().
*
* After executing this method, the current stack depth might be less than
* 0.
*/
static final void storeStack(CtClreplaced[] params, boolean isStaticCall, int regno, Bytecode bytecode) {
storeStack0(0, params.length, params, regno + 1, bytecode);
if (isStaticCall) {
bytecode.addOpcode(ACONST_NULL);
}
bytecode.addAstore(regno);
}
private static void storeStack0(int i, int n, CtClreplaced[] params, int regno, Bytecode bytecode) {
if (i >= n) {
return;
}
CtClreplaced c = params[i];
int size;
if (c instanceof CtPrimitiveType) {
size = ((CtPrimitiveType) c).getDataSize();
} else {
size = 1;
}
storeStack0(i + 1, n, params, regno + size, bytecode);
bytecode.addStore(regno, c);
}
// The implementation of replace() should call thisClreplaced.checkModify()
// so that isModify() will return true. Otherwise, thisClreplaced.clreplacedfile
// might be released during compilation and the compiler might generate
// bytecode with a wrong copy of ConstPool.
/**
* Replaces this expression with the bytecode derived from
* the given source text.
*
* @param statement
* a Java statement except try-catch.
*/
public abstract void replace(String statement) throws CannotCompileException;
/**
* Replaces this expression with the bytecode derived from
* the given source text and <code>ExprEditor</code>.
*
* @param statement
* a Java statement except try-catch.
* @param recursive
* if not null, the subsreplaceduted bytecode
* is recursively processed by the given
* <code>ExprEditor</code>.
* @since 3.1
*/
public void replace(String statement, ExprEditor recursive) throws CannotCompileException {
replace(statement);
if (recursive != null) {
runEditor(recursive, iterator);
}
}
protected void replace0(int pos, Bytecode bytecode, int size) throws BadBytecode {
byte[] code = bytecode.get();
edited = true;
int gap = code.length - size;
for (int i = 0; i < size; ++i) {
iterator.writeByte(NOP, pos + i);
}
if (gap > 0) {
pos = iterator.insertGapAt(pos, gap, false).position;
}
iterator.write(code, pos);
iterator.insert(bytecode.getExceptionTable(), pos);
maxLocals = bytecode.getMaxLocals();
maxStack = bytecode.getMaxStack();
}
protected void runEditor(ExprEditor ed, CodeIterator oldIterator) throws CannotCompileException {
CodeAttribute codeAttr = oldIterator.get();
int orgLocals = codeAttr.getMaxLocals();
int orgStack = codeAttr.getMaxStack();
int newLocals = locals();
codeAttr.setMaxStack(stack());
codeAttr.setMaxLocals(newLocals);
ExprEditor.LoopContext context = new ExprEditor.LoopContext(newLocals);
int size = oldIterator.getCodeLength();
int endPos = oldIterator.lookAhead();
oldIterator.move(currentPos);
if (ed.doit(thisClreplaced, thisMethod, context, oldIterator, endPos)) {
edited = true;
}
oldIterator.move(endPos + oldIterator.getCodeLength() - size);
codeAttr.setMaxLocals(orgLocals);
codeAttr.setMaxStack(orgStack);
maxLocals = context.maxLocals;
maxStack += context.maxStack;
}
}
19
Source : Expr.java
with Apache License 2.0
from ifeilong
with Apache License 2.0
from ifeilong
private static void addClreplaced(List<CtClreplaced> list, CtClreplaced c) {
if (list.contains(c)) {
return;
}
list.add(c);
}
19
Source : Expr.java
with Apache License 2.0
from ifeilong
with Apache License 2.0
from ifeilong
static final boolean checkResultValue(CtClreplaced retType, String prog) throws CannotCompileException {
/*
* Is $_ included in the source code?
*/
boolean hasIt = (prog.indexOf(Javac.resultVarName) >= 0);
if (!hasIt && retType != CtClreplaced.voidType) {
throw new CannotCompileException("the resulting value is not stored in " + Javac.resultVarName);
}
return hasIt;
}
19
Source : TransformReadField.java
with Apache License 2.0
from ifeilong
with Apache License 2.0
from ifeilong
public clreplaced TransformReadField extends Transformer {
protected String fieldname;
protected CtClreplaced fieldClreplaced;
protected boolean isPrivate;
protected String methodClreplacedname, methodName;
public TransformReadField(Transformer next, CtField field, String methodClreplacedname, String methodName) {
super(next);
this.fieldClreplaced = field.getDeclaringClreplaced();
this.fieldname = field.getName();
this.methodClreplacedname = methodClreplacedname;
this.methodName = methodName;
this.isPrivate = Modifier.isPrivate(field.getModifiers());
}
static String isField(ClreplacedPool pool, ConstPool cp, CtClreplaced fclreplaced, String fname, boolean is_private, int index) {
if (!cp.getFieldrefName(index).equals(fname)) {
return null;
}
try {
CtClreplaced c = pool.get(cp.getFieldrefClreplacedName(index));
if (c == fclreplaced || (!is_private && isFieldInSuper(c, fclreplaced, fname))) {
return cp.getFieldrefType(index);
}
} catch (NotFoundException e) {
}
return null;
}
static boolean isFieldInSuper(CtClreplaced clazz, CtClreplaced fclreplaced, String fname) {
if (!clazz.subclreplacedOf(fclreplaced)) {
return false;
}
try {
CtField f = clazz.getField(fname);
return f.getDeclaringClreplaced() == fclreplaced;
} catch (NotFoundException e) {
}
return false;
}
@Override
public int transform(CtClreplaced tclazz, int pos, CodeIterator iterator, ConstPool cp) throws BadBytecode {
int c = iterator.byteAt(pos);
if (c == GETFIELD || c == GETSTATIC) {
int index = iterator.u16bitAt(pos + 1);
String typedesc = isField(tclazz.getClreplacedPool(), cp, fieldClreplaced, fieldname, isPrivate, index);
if (typedesc != null) {
if (c == GETSTATIC) {
iterator.move(pos);
// insertGap() may insert 4 bytes.
pos = iterator.insertGap(1);
iterator.writeByte(ACONST_NULL, pos);
pos = iterator.next();
}
String type = "(Ljava/lang/Object;)" + typedesc;
int mi = cp.addClreplacedInfo(methodClreplacedname);
int methodref = cp.addMethodrefInfo(mi, methodName, type);
iterator.writeByte(INVOKESTATIC, pos);
iterator.write16bit(methodref, pos + 1);
return pos;
}
}
return pos;
}
}
19
Source : TransformReadField.java
with Apache License 2.0
from ifeilong
with Apache License 2.0
from ifeilong
static boolean isFieldInSuper(CtClreplaced clazz, CtClreplaced fclreplaced, String fname) {
if (!clazz.subclreplacedOf(fclreplaced)) {
return false;
}
try {
CtField f = clazz.getField(fname);
return f.getDeclaringClreplaced() == fclreplaced;
} catch (NotFoundException e) {
}
return false;
}
19
Source : TypeChecker.java
with Apache License 2.0
from ifeilong
with Apache License 2.0
from ifeilong
public clreplaced TypeChecker extends Visitor implements Opcode, TokenId {
static final String javaLangObject = "java.lang.Object";
static final String jvmJavaLangObject = "java/lang/Object";
static final String jvmJavaLangString = "java/lang/String";
static final String jvmJavaLangClreplaced = "java/lang/Clreplaced";
/*
* The following fields are used by atXXX() methods
* for returning the type of the compiled expression.
*/
// VOID, NULL, CLreplaced, BOOLEAN, INT, ...
protected int exprType;
protected int arrayDim;
// JVM-internal representation
protected String clreplacedName;
protected MemberResolver resolver;
protected CtClreplaced thisClreplaced;
protected MethodInfo thisMethod;
public TypeChecker(CtClreplaced cc, ClreplacedPool cp) {
resolver = new MemberResolver(cp);
thisClreplaced = cc;
thisMethod = null;
}
/*
* Converts an array of tuples of exprType, arrayDim, and clreplacedName
* into a String object.
*/
protected static String argTypesToString(int[] types, int[] dims, String[] cnames) {
StringBuffer sbuf = new StringBuffer();
sbuf.append('(');
int n = types.length;
if (n > 0) {
int i = 0;
while (true) {
typeToString(sbuf, types[i], dims[i], cnames[i]);
if (++i < n) {
sbuf.append(',');
} else {
break;
}
}
}
sbuf.append(')');
return sbuf.toString();
}
/*
* Converts a tuple of exprType, arrayDim, and clreplacedName
* into a String object.
*/
protected static StringBuffer typeToString(StringBuffer sbuf, int type, int dim, String cname) {
String s;
if (type == CLreplaced) {
s = MemberResolver.jvmToJavaName(cname);
} else if (type == NULL) {
s = "Object";
} else {
try {
s = MemberResolver.getTypeName(type);
} catch (CompileError e) {
s = "?";
}
}
sbuf.append(s);
while (dim-- > 0) {
sbuf.append("[]");
}
return sbuf;
}
/**
* Records the currently compiled method.
*/
public void setThisMethod(MethodInfo m) {
thisMethod = m;
}
protected static void fatal() throws CompileError {
throw new CompileError("fatal");
}
/**
* Returns the JVM-internal representation of this clreplaced name.
*/
protected String getThisName() {
return MemberResolver.javaToJvmName(thisClreplaced.getName());
}
/**
* Returns the JVM-internal representation of this super clreplaced name.
*/
protected String getSuperName() throws CompileError {
return MemberResolver.javaToJvmName(MemberResolver.getSuperclreplaced(thisClreplaced).getName());
}
/*
* Converts a clreplaced name into a JVM-internal representation.
*
* It may also expand a simple clreplaced name to java.lang.*.
* For example, this converts Object into java/lang/Object.
*/
protected String resolveClreplacedName(ASTList name) throws CompileError {
return resolver.resolveClreplacedName(name);
}
/*
* Expands a simple clreplaced name to java.lang.*.
* For example, this converts Object into java/lang/Object.
*/
protected String resolveClreplacedName(String jvmName) throws CompileError {
return resolver.resolveJvmClreplacedName(jvmName);
}
@Override
public void atNewExpr(NewExpr expr) throws CompileError {
if (expr.isArray()) {
atNewArrayExpr(expr);
} else {
CtClreplaced clazz = resolver.lookupClreplacedByName(expr.getClreplacedName());
String cname = clazz.getName();
ASTList args = expr.getArguments();
atMethodCallCore(clazz, MethodInfo.nameInit, args);
exprType = CLreplaced;
arrayDim = 0;
clreplacedName = MemberResolver.javaToJvmName(cname);
}
}
public void atNewArrayExpr(NewExpr expr) throws CompileError {
int type = expr.getArrayType();
ASTList size = expr.getArraySize();
ASTList clreplacedname = expr.getClreplacedName();
ASTree init = expr.getInitializer();
if (init != null) {
init.accept(this);
}
if (size.length() > 1) {
atMultiNewArray(type, clreplacedname, size);
} else {
ASTree sizeExpr = size.head();
if (sizeExpr != null) {
sizeExpr.accept(this);
}
exprType = type;
arrayDim = 1;
if (type == CLreplaced) {
clreplacedName = resolveClreplacedName(clreplacedname);
} else {
clreplacedName = null;
}
}
}
@Override
public void atArrayInit(ArrayInit init) throws CompileError {
ASTList list = init;
while (list != null) {
ASTree h = list.head();
list = list.tail();
if (h != null) {
h.accept(this);
}
}
}
protected void atMultiNewArray(int type, ASTList clreplacedname, ASTList size) throws CompileError {
@SuppressWarnings("unused")
int count, dim;
dim = size.length();
for (count = 0; size != null; size = size.tail()) {
ASTree s = size.head();
if (s == null) {
// int[][][] a = new int[3][4][];
break;
}
++count;
s.accept(this);
}
exprType = type;
arrayDim = dim;
if (type == CLreplaced) {
clreplacedName = resolveClreplacedName(clreplacedname);
} else {
clreplacedName = null;
}
}
@Override
public void atreplacedignExpr(replacedignExpr expr) throws CompileError {
// =, %=, &=, *=, /=, +=, -=, ^=, |=, <<=, >>=, >>>=
int op = expr.getOperator();
ASTree left = expr.oprand1();
ASTree right = expr.oprand2();
if (left instanceof Variable) {
atVariablereplacedign(expr, op, (Variable) left, ((Variable) left).getDeclarator(), right);
} else {
if (left instanceof Expr) {
Expr e = (Expr) left;
if (e.getOperator() == ARRAY) {
atArrayreplacedign(expr, op, (Expr) left, right);
return;
}
}
atFieldreplacedign(expr, op, left, right);
}
}
/*
* op is either =, %=, &=, *=, /=, +=, -=, ^=, |=, <<=, >>=, or >>>=.
*
* expr and var can be null.
*/
private void atVariablereplacedign(Expr expr, int op, Variable var, Declarator d, ASTree right) throws CompileError {
int varType = d.getType();
int varArray = d.getArrayDim();
String varClreplaced = d.getClreplacedName();
if (op != '=') {
atVariable(var);
}
right.accept(this);
exprType = varType;
arrayDim = varArray;
clreplacedName = varClreplaced;
}
private void atArrayreplacedign(Expr expr, int op, Expr array, ASTree right) throws CompileError {
atArrayRead(array.oprand1(), array.oprand2());
int aType = exprType;
int aDim = arrayDim;
String cname = clreplacedName;
right.accept(this);
exprType = aType;
arrayDim = aDim;
clreplacedName = cname;
}
protected void atFieldreplacedign(Expr expr, int op, ASTree left, ASTree right) throws CompileError {
CtField f = fieldAccess(left);
atFieldRead(f);
int fType = exprType;
int fDim = arrayDim;
String cname = clreplacedName;
right.accept(this);
exprType = fType;
arrayDim = fDim;
clreplacedName = cname;
}
@Override
public void atCondExpr(CondExpr expr) throws CompileError {
booleanExpr(expr.condExpr());
expr.thenExpr().accept(this);
int type1 = exprType;
int dim1 = arrayDim;
@SuppressWarnings("unused")
String cname1 = clreplacedName;
expr.elseExpr().accept(this);
if (dim1 == 0 && dim1 == arrayDim) {
if (CodeGen.rightIsStrong(type1, exprType)) {
expr.setThen(new CastExpr(exprType, 0, expr.thenExpr()));
} else if (CodeGen.rightIsStrong(exprType, type1)) {
expr.setElse(new CastExpr(type1, 0, expr.elseExpr()));
exprType = type1;
}
}
}
/*
* If atBinExpr() subsreplacedutes a new expression for the original
* binary-operator expression, it changes the operator name to '+'
* (if the original is not '+') and sets the new expression to the
* left-hand-side expression and null to the right-hand-side expression.
*/
@Override
public void atBinExpr(BinExpr expr) throws CompileError {
int token = expr.getOperator();
int k = CodeGen.lookupBinOp(token);
if (k >= 0) {
/*
* arithmetic operators: +, -, *, /, %, |, ^, &, <<, >>, >>>
*/
if (token == '+') {
Expr e = atPlusExpr(expr);
if (e != null) {
/*
* String concatenation has been translated into
* an expression using StringBuffer.
*/
e = CallExpr.makeCall(Expr.make('.', e, new Member("toString")), null);
expr.setOprand1(e);
// <---- look at this!
expr.setOprand2(null);
clreplacedName = jvmJavaLangString;
}
} else {
ASTree left = expr.oprand1();
ASTree right = expr.oprand2();
left.accept(this);
int type1 = exprType;
right.accept(this);
if (!isConstant(expr, token, left, right)) {
computeBinExprType(expr, token, type1);
}
}
} else {
/*
* equation: &&, ||, ==, !=, <=, >=, <, >
*/
booleanExpr(expr);
}
}
/*
* EXPR must be a + expression.
* atPlusExpr() returns non-null if the given expression is string
* concatenation. The returned value is "new StringBuffer().append..".
*/
private Expr atPlusExpr(BinExpr expr) throws CompileError {
ASTree left = expr.oprand1();
ASTree right = expr.oprand2();
if (right == null) {
// this expression has been already type-checked.
// see atBinExpr() above.
left.accept(this);
return null;
}
if (isPlusExpr(left)) {
Expr newExpr = atPlusExpr((BinExpr) left);
if (newExpr != null) {
right.accept(this);
exprType = CLreplaced;
arrayDim = 0;
clreplacedName = "java/lang/StringBuffer";
return makeAppendCall(newExpr, right);
}
} else {
left.accept(this);
}
int type1 = exprType;
int dim1 = arrayDim;
String cname = clreplacedName;
right.accept(this);
if (isConstant(expr, '+', left, right)) {
return null;
}
if ((type1 == CLreplaced && dim1 == 0 && jvmJavaLangString.equals(cname)) || (exprType == CLreplaced && arrayDim == 0 && jvmJavaLangString.equals(clreplacedName))) {
ASTList sbufClreplaced = ASTList.make(new Symbol("java"), new Symbol("lang"), new Symbol("StringBuffer"));
ASTree e = new NewExpr(sbufClreplaced, null);
exprType = CLreplaced;
arrayDim = 0;
clreplacedName = "java/lang/StringBuffer";
return makeAppendCall(makeAppendCall(e, left), right);
}
computeBinExprType(expr, '+', type1);
return null;
}
private boolean isConstant(BinExpr expr, int op, ASTree left, ASTree right) throws CompileError {
left = stripPlusExpr(left);
right = stripPlusExpr(right);
ASTree newExpr = null;
if (left instanceof StringL && right instanceof StringL && op == '+') {
newExpr = new StringL(((StringL) left).get() + ((StringL) right).get());
} else if (left instanceof IntConst) {
newExpr = ((IntConst) left).compute(op, right);
} else if (left instanceof DoubleConst) {
newExpr = ((DoubleConst) left).compute(op, right);
}
if (newExpr == null) {
// not a constant expression
return false;
}
expr.setOperator('+');
expr.setOprand1(newExpr);
expr.setOprand2(null);
// for setting exprType, arrayDim, ...
newExpr.accept(this);
return true;
}
/*
* CodeGen.atSwitchStmnt() also calls stripPlusExpr().
*/
static ASTree stripPlusExpr(ASTree expr) {
if (expr instanceof BinExpr) {
BinExpr e = (BinExpr) expr;
if (e.getOperator() == '+' && e.oprand2() == null) {
return e.getLeft();
}
} else if (expr instanceof Expr) {
// note: BinExpr extends Expr.
Expr e = (Expr) expr;
int op = e.getOperator();
if (op == MEMBER) {
ASTree cexpr = getConstantFieldValue((Member) e.oprand2());
if (cexpr != null) {
return cexpr;
}
} else if (op == '+' && e.getRight() == null) {
return e.getLeft();
}
} else if (expr instanceof Member) {
ASTree cexpr = getConstantFieldValue((Member) expr);
if (cexpr != null) {
return cexpr;
}
}
return expr;
}
/**
* If MEM is a static final field, this method returns a constant
* expression representing the value of that field.
*/
private static ASTree getConstantFieldValue(Member mem) {
return getConstantFieldValue(mem.getField());
}
public static ASTree getConstantFieldValue(CtField f) {
if (f == null) {
return null;
}
Object value = f.getConstantValue();
if (value == null) {
return null;
}
if (value instanceof String) {
return new StringL((String) value);
} else if (value instanceof Double || value instanceof Float) {
int token = (value instanceof Double) ? DoubleConstant : FloatConstant;
return new DoubleConst(((Number) value).doubleValue(), token);
} else if (value instanceof Number) {
int token = (value instanceof Long) ? LongConstant : IntConstant;
return new IntConst(((Number) value).longValue(), token);
} else if (value instanceof Boolean) {
return new Keyword(((Boolean) value).booleanValue() ? TokenId.TRUE : TokenId.FALSE);
} else {
return null;
}
}
private static boolean isPlusExpr(ASTree expr) {
if (expr instanceof BinExpr) {
BinExpr bexpr = (BinExpr) expr;
int token = bexpr.getOperator();
return token == '+';
}
return false;
}
private static Expr makeAppendCall(ASTree target, ASTree arg) {
return CallExpr.makeCall(Expr.make('.', target, new Member("append")), new ASTList(arg));
}
private void computeBinExprType(BinExpr expr, int token, int type1) throws CompileError {
// arrayDim should be 0.
int type2 = exprType;
if (token == LSHIFT || token == RSHIFT || token == ARSHIFT) {
exprType = type1;
} else {
insertCast(expr, type1, type2);
}
if (CodeGen.isP_INT(exprType) && exprType != BOOLEAN) {
// type1 may be BYTE, ...
exprType = INT;
}
}
private void booleanExpr(ASTree expr) throws CompileError {
int op = CodeGen.getCompOperator(expr);
if (op == EQ) {
// ==, !=, ...
BinExpr bexpr = (BinExpr) expr;
bexpr.oprand1().accept(this);
int type1 = exprType;
int dim1 = arrayDim;
bexpr.oprand2().accept(this);
if (dim1 == 0 && arrayDim == 0) {
insertCast(bexpr, type1, exprType);
}
} else if (op == '!') {
((Expr) expr).oprand1().accept(this);
} else if (op == ANDAND || op == OROR) {
BinExpr bexpr = (BinExpr) expr;
bexpr.oprand1().accept(this);
bexpr.oprand2().accept(this);
} else {
expr.accept(this);
}
exprType = BOOLEAN;
arrayDim = 0;
}
private void insertCast(BinExpr expr, int type1, int type2) throws CompileError {
if (CodeGen.rightIsStrong(type1, type2)) {
expr.setLeft(new CastExpr(type2, 0, expr.oprand1()));
} else {
exprType = type1;
}
}
@Override
public void atCastExpr(CastExpr expr) throws CompileError {
String cname = resolveClreplacedName(expr.getClreplacedName());
expr.getOprand().accept(this);
exprType = expr.getType();
arrayDim = expr.getArrayDim();
clreplacedName = cname;
}
@Override
public void atInstanceOfExpr(InstanceOfExpr expr) throws CompileError {
expr.getOprand().accept(this);
exprType = BOOLEAN;
arrayDim = 0;
}
@Override
public void atExpr(Expr expr) throws CompileError {
// array access, member access,
// (unary) +, (unary) -, ++, --, !, ~
int token = expr.getOperator();
ASTree oprand = expr.oprand1();
if (token == '.') {
String member = ((Symbol) expr.oprand2()).get();
if (member.equals("length")) {
try {
atArrayLength(expr);
} catch (NoFieldException nfe) {
// length might be a clreplaced or package name.
atFieldRead(expr);
}
} else if (member.equals("clreplaced")) {
// .clreplaced
atClreplacedObject(expr);
} else {
atFieldRead(expr);
}
} else if (token == MEMBER) {
// field read
String member = ((Symbol) expr.oprand2()).get();
if (member.equals("clreplaced")) {
// .clreplaced
atClreplacedObject(expr);
} else {
atFieldRead(expr);
}
} else if (token == ARRAY) {
atArrayRead(oprand, expr.oprand2());
} else if (token == PLUSPLUS || token == MINUSMINUS) {
atPlusPlus(token, oprand, expr);
} else if (token == '!') {
booleanExpr(expr);
} else if (token == CALL) {
fatal();
} else {
oprand.accept(this);
if (!isConstant(expr, token, oprand)) {
if (token == '-' || token == '~') {
if (CodeGen.isP_INT(exprType)) {
// type may be BYTE, ...
exprType = INT;
}
}
}
}
}
private boolean isConstant(Expr expr, int op, ASTree oprand) {
oprand = stripPlusExpr(oprand);
if (oprand instanceof IntConst) {
IntConst c = (IntConst) oprand;
long v = c.get();
if (op == '-') {
v = -v;
} else if (op == '~') {
v = ~v;
} else {
return false;
}
c.set(v);
} else if (oprand instanceof DoubleConst) {
DoubleConst c = (DoubleConst) oprand;
if (op == '-') {
c.set(-c.get());
} else {
return false;
}
} else {
return false;
}
expr.setOperator('+');
return true;
}
@Override
public void atCallExpr(CallExpr expr) throws CompileError {
String mname = null;
CtClreplaced targetClreplaced = null;
ASTree method = expr.oprand1();
ASTList args = (ASTList) expr.oprand2();
if (method instanceof Member) {
mname = ((Member) method).get();
targetClreplaced = thisClreplaced;
} else if (method instanceof Keyword) {
// constructor
// <init>
mname = MethodInfo.nameInit;
if (((Keyword) method).get() == SUPER) {
targetClreplaced = MemberResolver.getSuperclreplaced(thisClreplaced);
} else {
targetClreplaced = thisClreplaced;
}
} else if (method instanceof Expr) {
Expr e = (Expr) method;
mname = ((Symbol) e.oprand2()).get();
int op = e.getOperator();
if (op == MEMBER) {
targetClreplaced = resolver.lookupClreplaced(((Symbol) e.oprand1()).get(), false);
} else if (op == '.') {
ASTree target = e.oprand1();
String clreplacedFollowedByDotSuper = isDotSuper(target);
if (clreplacedFollowedByDotSuper != null) {
targetClreplaced = MemberResolver.getSuperInterface(thisClreplaced, clreplacedFollowedByDotSuper);
} else {
try {
target.accept(this);
} catch (NoFieldException nfe) {
if (nfe.getExpr() != target) {
throw nfe;
}
// it should be a static method.
exprType = CLreplaced;
arrayDim = 0;
// JVM-internal
clreplacedName = nfe.getField();
e.setOperator(MEMBER);
e.setOprand1(new Symbol(MemberResolver.jvmToJavaName(clreplacedName)));
}
if (arrayDim > 0) {
targetClreplaced = resolver.lookupClreplaced(javaLangObject, true);
} else if (exprType == CLreplaced) /* && arrayDim == 0 */
{
targetClreplaced = resolver.lookupClreplacedByJvmName(clreplacedName);
} else {
badMethod();
}
}
} else {
badMethod();
}
} else {
fatal();
}
MemberResolver.Method minfo = atMethodCallCore(targetClreplaced, mname, args);
expr.setMethod(minfo);
}
private static void badMethod() throws CompileError {
throw new CompileError("bad method");
}
/**
* Returns non-null if target is something like Foo.super
* for accessing the default method in an interface.
* Otherwise, null.
*
* @return the clreplaced name followed by {@code .super} or null.
*/
static String isDotSuper(ASTree target) {
if (target instanceof Expr) {
Expr e = (Expr) target;
if (e.getOperator() == '.') {
ASTree right = e.oprand2();
if (right instanceof Keyword && ((Keyword) right).get() == SUPER) {
return ((Symbol) e.oprand1()).get();
}
}
}
return null;
}
/**
* @return a pair of the clreplaced declaring the invoked method
* and the MethodInfo of that method. Never null.
*/
public MemberResolver.Method atMethodCallCore(CtClreplaced targetClreplaced, String mname, ASTList args) throws CompileError {
int nargs = getMethodArgsLength(args);
int[] types = new int[nargs];
int[] dims = new int[nargs];
String[] cnames = new String[nargs];
atMethodArgs(args, types, dims, cnames);
MemberResolver.Method found = resolver.lookupMethod(targetClreplaced, thisClreplaced, thisMethod, mname, types, dims, cnames);
if (found == null) {
String clazz = targetClreplaced.getName();
String signature = argTypesToString(types, dims, cnames);
String msg;
if (mname.equals(MethodInfo.nameInit)) {
msg = "cannot find constructor " + clazz + signature;
} else {
msg = mname + signature + " not found in " + clazz;
}
throw new CompileError(msg);
}
String desc = found.info.getDescriptor();
setReturnType(desc);
return found;
}
public int getMethodArgsLength(ASTList args) {
return ASTList.length(args);
}
public void atMethodArgs(ASTList args, int[] types, int[] dims, String[] cnames) throws CompileError {
int i = 0;
while (args != null) {
ASTree a = args.head();
a.accept(this);
types[i] = exprType;
dims[i] = arrayDim;
cnames[i] = clreplacedName;
++i;
args = args.tail();
}
}
void setReturnType(String desc) throws CompileError {
int i = desc.indexOf(')');
if (i < 0) {
badMethod();
}
char c = desc.charAt(++i);
int dim = 0;
while (c == '[') {
++dim;
c = desc.charAt(++i);
}
arrayDim = dim;
if (c == 'L') {
int j = desc.indexOf(';', i + 1);
if (j < 0) {
badMethod();
}
exprType = CLreplaced;
clreplacedName = desc.substring(i + 1, j);
} else {
exprType = MemberResolver.descToType(c);
clreplacedName = null;
}
}
private void atFieldRead(ASTree expr) throws CompileError {
atFieldRead(fieldAccess(expr));
}
private void atFieldRead(CtField f) throws CompileError {
FieldInfo finfo = f.getFieldInfo2();
String type = finfo.getDescriptor();
int i = 0;
int dim = 0;
char c = type.charAt(i);
while (c == '[') {
++dim;
c = type.charAt(++i);
}
arrayDim = dim;
exprType = MemberResolver.descToType(c);
if (c == 'L') {
clreplacedName = type.substring(i + 1, type.indexOf(';', i + 1));
} else {
clreplacedName = null;
}
}
/*
* if EXPR is to access a static field, fieldAccess() translates EXPR
* into an expression using '#' (MEMBER). For example, it translates
* java.lang.Integer.TYPE into java.lang.Integer#TYPE. This translation
* speeds up type resolution by MemberCodeGen.
*/
protected CtField fieldAccess(ASTree expr) throws CompileError {
if (expr instanceof Member) {
Member mem = (Member) expr;
String name = mem.get();
try {
CtField f = thisClreplaced.getField(name);
if (Modifier.isStatic(f.getModifiers())) {
mem.setField(f);
}
return f;
} catch (NotFoundException e) {
// EXPR might be part of a static member access?
throw new NoFieldException(name, expr);
}
} else if (expr instanceof Expr) {
Expr e = (Expr) expr;
int op = e.getOperator();
if (op == MEMBER) {
Member mem = (Member) e.oprand2();
CtField f = resolver.lookupField(((Symbol) e.oprand1()).get(), mem);
mem.setField(f);
return f;
} else if (op == '.') {
try {
e.oprand1().accept(this);
} catch (NoFieldException nfe) {
if (nfe.getExpr() != e.oprand1()) {
throw nfe;
}
/*
* EXPR should be a static field.
* If EXPR might be part of a qualified clreplaced name,
* lookupFieldByJvmName2() throws NoFieldException.
*/
return fieldAccess2(e, nfe.getField());
}
CompileError err = null;
try {
if (exprType == CLreplaced && arrayDim == 0) {
return resolver.lookupFieldByJvmName(clreplacedName, (Symbol) e.oprand2());
}
} catch (CompileError ce) {
err = ce;
}
/*
* If a filed name is the same name as a package's,
* a static member of a clreplaced in that package is not
* visible. For example,
*
* clreplaced Foo {
* int javreplacedist;
* }
*
* It is impossible to add the following method:
*
* String m() { return javreplacedist.CtClreplaced.intType.toString(); }
*
* because javreplacedist is a field name. However, this is
* often inconvenient, this compiler allows it. The following
* code is for that.
*/
ASTree oprnd1 = e.oprand1();
if (oprnd1 instanceof Symbol) {
return fieldAccess2(e, ((Symbol) oprnd1).get());
}
if (err != null) {
throw err;
}
}
}
throw new CompileError("bad filed access");
}
private CtField fieldAccess2(Expr e, String jvmClreplacedName) throws CompileError {
Member fname = (Member) e.oprand2();
CtField f = resolver.lookupFieldByJvmName2(jvmClreplacedName, fname, e);
e.setOperator(MEMBER);
e.setOprand1(new Symbol(MemberResolver.jvmToJavaName(jvmClreplacedName)));
fname.setField(f);
return f;
}
public void atClreplacedObject(Expr expr) throws CompileError {
exprType = CLreplaced;
arrayDim = 0;
clreplacedName = jvmJavaLangClreplaced;
}
public void atArrayLength(Expr expr) throws CompileError {
expr.oprand1().accept(this);
if (arrayDim == 0) {
throw new NoFieldException("length", expr);
}
exprType = INT;
arrayDim = 0;
}
public void atArrayRead(ASTree array, ASTree index) throws CompileError {
array.accept(this);
int type = exprType;
int dim = arrayDim;
String cname = clreplacedName;
index.accept(this);
exprType = type;
arrayDim = dim - 1;
clreplacedName = cname;
}
private void atPlusPlus(int token, ASTree oprand, Expr expr) throws CompileError {
// ++i or i++?
boolean isPost = oprand == null;
if (isPost) {
oprand = expr.oprand2();
}
if (oprand instanceof Variable) {
Declarator d = ((Variable) oprand).getDeclarator();
exprType = d.getType();
arrayDim = d.getArrayDim();
} else {
if (oprand instanceof Expr) {
Expr e = (Expr) oprand;
if (e.getOperator() == ARRAY) {
atArrayRead(e.oprand1(), e.oprand2());
// arrayDim should be 0.
int t = exprType;
if (t == INT || t == BYTE || t == CHAR || t == SHORT) {
exprType = INT;
}
return;
}
}
atFieldPlusPlus(oprand);
}
}
protected void atFieldPlusPlus(ASTree oprand) throws CompileError {
CtField f = fieldAccess(oprand);
atFieldRead(f);
int t = exprType;
if (t == INT || t == BYTE || t == CHAR || t == SHORT) {
exprType = INT;
}
}
@Override
public void atMember(Member mem) throws CompileError {
atFieldRead(mem);
}
@Override
public void atVariable(Variable v) throws CompileError {
Declarator d = v.getDeclarator();
exprType = d.getType();
arrayDim = d.getArrayDim();
clreplacedName = d.getClreplacedName();
}
@Override
public void atKeyword(Keyword k) throws CompileError {
arrayDim = 0;
int token = k.get();
switch(token) {
case TRUE:
case FALSE:
exprType = BOOLEAN;
break;
case NULL:
exprType = NULL;
break;
case THIS:
case SUPER:
exprType = CLreplaced;
if (token == THIS) {
clreplacedName = getThisName();
} else {
clreplacedName = getSuperName();
}
break;
default:
fatal();
}
}
@Override
public void atStringL(StringL s) throws CompileError {
exprType = CLreplaced;
arrayDim = 0;
clreplacedName = jvmJavaLangString;
}
@Override
public void atIntConst(IntConst i) throws CompileError {
arrayDim = 0;
int type = i.getType();
if (type == IntConstant || type == CharConstant) {
exprType = (type == IntConstant ? INT : CHAR);
} else {
exprType = LONG;
}
}
@Override
public void atDoubleConst(DoubleConst d) throws CompileError {
arrayDim = 0;
if (d.getType() == DoubleConstant) {
exprType = DOUBLE;
} else {
exprType = FLOAT;
}
}
}
19
Source : MemberResolver.java
with Apache License 2.0
from ifeilong
with Apache License 2.0
from ifeilong
/**
* @param clreplacedname
* jvm clreplaced name.
*/
public CtClreplaced lookupClreplaced(int type, int dim, String clreplacedname) throws CompileError {
String cname = "";
CtClreplaced clazz;
if (type == CLreplaced) {
clazz = lookupClreplacedByJvmName(clreplacedname);
if (dim > 0) {
cname = clazz.getName();
} else {
return clazz;
}
} else {
cname = getTypeName(type);
}
while (dim-- > 0) {
cname += "[]";
}
return lookupClreplaced(cname, false);
}
19
Source : MemberResolver.java
with Apache License 2.0
from ifeilong
with Apache License 2.0
from ifeilong
private CtClreplaced lookupClreplaced0(String clreplacedname, boolean notCheckInner) throws NotFoundException {
CtClreplaced cc = null;
do {
try {
cc = clreplacedPool.get(clreplacedname);
} catch (NotFoundException e) {
int i = clreplacedname.lastIndexOf('.');
if (notCheckInner || i < 0) {
throw e;
}
StringBuffer sbuf = new StringBuffer(clreplacedname);
sbuf.setCharAt(i, '$');
clreplacedname = sbuf.toString();
}
} while (cc == null);
return cc;
}
19
Source : MemberCodeGen.java
with Apache License 2.0
from ifeilong
with Apache License 2.0
from ifeilong
/* Code generator methods depending on javreplacedist.* clreplacedes.
*/
public clreplaced MemberCodeGen extends CodeGen {
protected MemberResolver resolver;
protected CtClreplaced thisClreplaced;
protected MethodInfo thisMethod;
protected boolean resultStatic;
public MemberCodeGen(Bytecode b, CtClreplaced cc, ClreplacedPool cp) {
super(b);
resolver = new MemberResolver(cp);
thisClreplaced = cc;
thisMethod = null;
}
/**
* Returns the major version of the clreplaced file
* targeted by this compilation.
*/
public int getMajorVersion() {
ClreplacedFile cf = thisClreplaced.getClreplacedFile2();
if (cf == null) {
// JDK 1.3
return ClreplacedFile.MAJOR_VERSION;
}
return cf.getMajorVersion();
}
/**
* Records the currently compiled method.
*/
public void setThisMethod(CtMethod m) {
thisMethod = m.getMethodInfo2();
if (typeChecker != null) {
typeChecker.setThisMethod(thisMethod);
}
}
public CtClreplaced getThisClreplaced() {
return thisClreplaced;
}
/**
* Returns the JVM-internal representation of this clreplaced name.
*/
@Override
protected String getThisName() {
return MemberResolver.javaToJvmName(thisClreplaced.getName());
}
/**
* Returns the JVM-internal representation of this super clreplaced name.
*/
@Override
protected String getSuperName() throws CompileError {
return MemberResolver.javaToJvmName(MemberResolver.getSuperclreplaced(thisClreplaced).getName());
}
@Override
protected void insertDefaultSuperCall() throws CompileError {
bytecode.addAload(0);
bytecode.addInvokespecial(MemberResolver.getSuperclreplaced(thisClreplaced), "<init>", "()V");
}
static clreplaced JsrHook extends ReturnHook {
List<int[]> jsrList;
CodeGen cgen;
int var;
JsrHook(CodeGen gen) {
super(gen);
jsrList = new ArrayList<>();
cgen = gen;
var = -1;
}
private int getVar(int size) {
if (var < 0) {
var = cgen.getMaxLocals();
cgen.incMaxLocals(size);
}
return var;
}
private void jsrJmp(Bytecode b) {
b.addOpcode(Opcode.GOTO);
jsrList.add(new int[] { b.currentPc(), var });
b.addIndex(0);
}
@Override
protected boolean doit(Bytecode b, int opcode) {
switch(opcode) {
case Opcode.RETURN:
jsrJmp(b);
break;
case ARETURN:
b.addAstore(getVar(1));
jsrJmp(b);
b.addAload(var);
break;
case IRETURN:
b.addIstore(getVar(1));
jsrJmp(b);
b.addIload(var);
break;
case LRETURN:
b.addLstore(getVar(2));
jsrJmp(b);
b.addLload(var);
break;
case DRETURN:
b.addDstore(getVar(2));
jsrJmp(b);
b.addDload(var);
break;
case FRETURN:
b.addFstore(getVar(1));
jsrJmp(b);
b.addFload(var);
break;
default:
throw new RuntimeException("fatal");
}
return false;
}
}
static clreplaced JsrHook2 extends ReturnHook {
int var;
int target;
JsrHook2(CodeGen gen, int[] retTarget) {
super(gen);
target = retTarget[0];
var = retTarget[1];
}
@Override
protected boolean doit(Bytecode b, int opcode) {
switch(opcode) {
case Opcode.RETURN:
break;
case ARETURN:
b.addAstore(var);
break;
case IRETURN:
b.addIstore(var);
break;
case LRETURN:
b.addLstore(var);
break;
case DRETURN:
b.addDstore(var);
break;
case FRETURN:
b.addFstore(var);
break;
default:
throw new RuntimeException("fatal");
}
b.addOpcode(Opcode.GOTO);
b.addIndex(target - b.currentPc() + 3);
return true;
}
}
@Override
protected void atTryStmnt(Stmnt st) throws CompileError {
Bytecode bc = bytecode;
Stmnt body = (Stmnt) st.getLeft();
if (body == null) {
return;
}
ASTList catchList = (ASTList) st.getRight().getLeft();
Stmnt finallyBlock = (Stmnt) st.getRight().getRight().getLeft();
List<Integer> gotoList = new ArrayList<>();
JsrHook jsrHook = null;
if (finallyBlock != null) {
jsrHook = new JsrHook(this);
}
int start = bc.currentPc();
body.accept(this);
int end = bc.currentPc();
if (start == end) {
throw new CompileError("empty try block");
}
boolean tryNotReturn = !hasReturned;
if (tryNotReturn) {
bc.addOpcode(Opcode.GOTO);
gotoList.add(bc.currentPc());
// correct later
bc.addIndex(0);
}
int var = getMaxLocals();
incMaxLocals(1);
while (catchList != null) {
// catch clause
Pair p = (Pair) catchList.head();
catchList = catchList.tail();
Declarator decl = (Declarator) p.getLeft();
Stmnt block = (Stmnt) p.getRight();
decl.setLocalVar(var);
CtClreplaced type = resolver.lookupClreplacedByJvmName(decl.getClreplacedName());
decl.setClreplacedName(MemberResolver.javaToJvmName(type.getName()));
bc.addExceptionHandler(start, end, bc.currentPc(), type);
bc.growStack(1);
bc.addAstore(var);
hasReturned = false;
if (block != null) {
block.accept(this);
}
if (!hasReturned) {
bc.addOpcode(Opcode.GOTO);
gotoList.add(bc.currentPc());
// correct later
bc.addIndex(0);
tryNotReturn = true;
}
}
if (finallyBlock != null) {
jsrHook.remove(this);
// catch (any) clause
int pcAnyCatch = bc.currentPc();
bc.addExceptionHandler(start, pcAnyCatch, pcAnyCatch, 0);
bc.growStack(1);
bc.addAstore(var);
hasReturned = false;
finallyBlock.accept(this);
if (!hasReturned) {
bc.addAload(var);
bc.addOpcode(ATHROW);
}
addFinally(jsrHook.jsrList, finallyBlock);
}
int pcEnd = bc.currentPc();
patchGoto(gotoList, pcEnd);
hasReturned = !tryNotReturn;
if (finallyBlock != null) {
if (tryNotReturn) {
finallyBlock.accept(this);
}
}
}
/**
* Adds a finally clause for earch return statement.
*/
private void addFinally(List<int[]> returnList, Stmnt finallyBlock) throws CompileError {
Bytecode bc = bytecode;
for (final int[] ret : returnList) {
int pc = ret[0];
bc.write16bit(pc, bc.currentPc() - pc + 1);
ReturnHook hook = new JsrHook2(this, ret);
finallyBlock.accept(this);
hook.remove(this);
if (!hasReturned) {
bc.addOpcode(Opcode.GOTO);
bc.addIndex(pc + 3 - bc.currentPc());
}
}
}
@Override
public void atNewExpr(NewExpr expr) throws CompileError {
if (expr.isArray()) {
atNewArrayExpr(expr);
} else {
CtClreplaced clazz = resolver.lookupClreplacedByName(expr.getClreplacedName());
String cname = clazz.getName();
ASTList args = expr.getArguments();
bytecode.addNew(cname);
bytecode.addOpcode(DUP);
atMethodCallCore(clazz, MethodInfo.nameInit, args, false, true, -1, null);
exprType = CLreplaced;
arrayDim = 0;
clreplacedName = MemberResolver.javaToJvmName(cname);
}
}
public void atNewArrayExpr(NewExpr expr) throws CompileError {
int type = expr.getArrayType();
ASTList size = expr.getArraySize();
ASTList clreplacedname = expr.getClreplacedName();
ArrayInit init = expr.getInitializer();
if (size.length() > 1) {
if (init != null) {
throw new CompileError("sorry, multi-dimensional array initializer " + "for new is not supported");
}
atMultiNewArray(type, clreplacedname, size);
return;
}
ASTree sizeExpr = size.head();
atNewArrayExpr2(type, sizeExpr, Declarator.astToClreplacedName(clreplacedname, '/'), init);
}
private void atNewArrayExpr2(int type, ASTree sizeExpr, String jvmClreplacedname, ArrayInit init) throws CompileError {
if (init == null) {
if (sizeExpr == null) {
throw new CompileError("no array size");
} else {
sizeExpr.accept(this);
}
} else if (sizeExpr == null) {
int s = init.length();
bytecode.addIconst(s);
} else {
throw new CompileError("unnecessary array size specified for new");
}
String elementClreplaced;
if (type == CLreplaced) {
elementClreplaced = resolveClreplacedName(jvmClreplacedname);
bytecode.addAnewarray(MemberResolver.jvmToJavaName(elementClreplaced));
} else {
elementClreplaced = null;
int atype = 0;
switch(type) {
case BOOLEAN:
atype = T_BOOLEAN;
break;
case CHAR:
atype = T_CHAR;
break;
case FLOAT:
atype = T_FLOAT;
break;
case DOUBLE:
atype = T_DOUBLE;
break;
case BYTE:
atype = T_BYTE;
break;
case SHORT:
atype = T_SHORT;
break;
case INT:
atype = T_INT;
break;
case LONG:
atype = T_LONG;
break;
default:
badNewExpr();
break;
}
bytecode.addOpcode(NEWARRAY);
bytecode.add(atype);
}
if (init != null) {
int s = init.length();
ASTList list = init;
for (int i = 0; i < s; i++) {
bytecode.addOpcode(DUP);
bytecode.addIconst(i);
list.head().accept(this);
if (!isRefType(type)) {
atNumCastExpr(exprType, type);
}
bytecode.addOpcode(getArrayWriteOp(type, 0));
list = list.tail();
}
}
exprType = type;
arrayDim = 1;
clreplacedName = elementClreplaced;
}
private static void badNewExpr() throws CompileError {
throw new CompileError("bad new expression");
}
@Override
protected void atArrayVariablereplacedign(ArrayInit init, int varType, int varArray, String varClreplaced) throws CompileError {
atNewArrayExpr2(varType, null, varClreplaced, init);
}
@Override
public void atArrayInit(ArrayInit init) throws CompileError {
throw new CompileError("array initializer is not supported");
}
protected void atMultiNewArray(int type, ASTList clreplacedname, ASTList size) throws CompileError {
int count, dim;
dim = size.length();
for (count = 0; size != null; size = size.tail()) {
ASTree s = size.head();
if (s == null) {
// int[][][] a = new int[3][4][];
break;
}
++count;
s.accept(this);
if (exprType != INT) {
throw new CompileError("bad type for array size");
}
}
String desc;
exprType = type;
arrayDim = dim;
if (type == CLreplaced) {
clreplacedName = resolveClreplacedName(clreplacedname);
desc = toJvmArrayName(clreplacedName, dim);
} else {
desc = toJvmTypeName(type, dim);
}
bytecode.addMultiNewarray(desc, count);
}
@Override
public void atCallExpr(CallExpr expr) throws CompileError {
String mname = null;
CtClreplaced targetClreplaced = null;
ASTree method = expr.oprand1();
ASTList args = (ASTList) expr.oprand2();
boolean isStatic = false;
boolean isSpecial = false;
int aload0pos = -1;
MemberResolver.Method cached = expr.getMethod();
if (method instanceof Member) {
mname = ((Member) method).get();
targetClreplaced = thisClreplaced;
if (inStaticMethod || (cached != null && cached.isStatic())) {
// should be static
isStatic = true;
} else {
aload0pos = bytecode.currentPc();
// this
bytecode.addAload(0);
}
} else if (method instanceof Keyword) {
// constructor
isSpecial = true;
// <init>
mname = MethodInfo.nameInit;
targetClreplaced = thisClreplaced;
if (inStaticMethod) {
throw new CompileError("a constructor cannot be static");
}
// this
bytecode.addAload(0);
if (((Keyword) method).get() == SUPER) {
targetClreplaced = MemberResolver.getSuperclreplaced(targetClreplaced);
}
} else if (method instanceof Expr) {
Expr e = (Expr) method;
mname = ((Symbol) e.oprand2()).get();
int op = e.getOperator();
if (op == MEMBER) {
// static method
targetClreplaced = resolver.lookupClreplaced(((Symbol) e.oprand1()).get(), false);
isStatic = true;
} else if (op == '.') {
ASTree target = e.oprand1();
String clreplacedFollowedByDotSuper = TypeChecker.isDotSuper(target);
if (clreplacedFollowedByDotSuper != null) {
isSpecial = true;
targetClreplaced = MemberResolver.getSuperInterface(thisClreplaced, clreplacedFollowedByDotSuper);
if (inStaticMethod || (cached != null && cached.isStatic())) {
// should be static
isStatic = true;
} else {
aload0pos = bytecode.currentPc();
// this
bytecode.addAload(0);
}
} else {
if (target instanceof Keyword) {
if (((Keyword) target).get() == SUPER) {
isSpecial = true;
}
}
try {
target.accept(this);
} catch (NoFieldException nfe) {
if (nfe.getExpr() != target) {
throw nfe;
}
// it should be a static method.
exprType = CLreplaced;
arrayDim = 0;
// JVM-internal
clreplacedName = nfe.getField();
isStatic = true;
}
if (arrayDim > 0) {
targetClreplaced = resolver.lookupClreplaced(javaLangObject, true);
} else if (exprType == CLreplaced) /* && arrayDim == 0 */
{
targetClreplaced = resolver.lookupClreplacedByJvmName(clreplacedName);
} else {
badMethod();
}
}
} else {
badMethod();
}
} else {
fatal();
}
atMethodCallCore(targetClreplaced, mname, args, isStatic, isSpecial, aload0pos, cached);
}
private static void badMethod() throws CompileError {
throw new CompileError("bad method");
}
/*
* atMethodCallCore() is also called by doit() in NewExpr.ProceedForNew
*
* @param targetClreplaced the clreplaced at which method lookup starts.
*
* @param found not null if the method look has been already done.
*/
public void atMethodCallCore(CtClreplaced targetClreplaced, String mname, ASTList args, boolean isStatic, boolean isSpecial, int aload0pos, MemberResolver.Method found) throws CompileError {
int nargs = getMethodArgsLength(args);
int[] types = new int[nargs];
int[] dims = new int[nargs];
String[] cnames = new String[nargs];
if (!isStatic && found != null && found.isStatic()) {
bytecode.addOpcode(POP);
isStatic = true;
}
@SuppressWarnings("unused")
int stack = bytecode.getStackDepth();
// generate code for evaluating arguments.
atMethodArgs(args, types, dims, cnames);
if (found == null) {
found = resolver.lookupMethod(targetClreplaced, thisClreplaced, thisMethod, mname, types, dims, cnames);
}
if (found == null) {
String msg;
if (mname.equals(MethodInfo.nameInit)) {
msg = "constructor not found";
} else {
msg = "Method " + mname + " not found in " + targetClreplaced.getName();
}
throw new CompileError(msg);
}
atMethodCallCore2(targetClreplaced, mname, isStatic, isSpecial, aload0pos, found);
}
private void atMethodCallCore2(CtClreplaced targetClreplaced, String mname, boolean isStatic, boolean isSpecial, int aload0pos, MemberResolver.Method found) throws CompileError {
CtClreplaced declClreplaced = found.declaring;
MethodInfo minfo = found.info;
String desc = minfo.getDescriptor();
int acc = minfo.getAccessFlags();
if (mname.equals(MethodInfo.nameInit)) {
isSpecial = true;
if (declClreplaced != targetClreplaced) {
throw new CompileError("no such constructor: " + targetClreplaced.getName());
}
if (declClreplaced != thisClreplaced && AccessFlag.isPrivate(acc)) {
desc = getAccessibleConstructor(desc, declClreplaced, minfo);
// the last parameter
bytecode.addOpcode(Opcode.ACONST_NULL);
}
} else if (AccessFlag.isPrivate(acc)) {
if (declClreplaced == thisClreplaced) {
isSpecial = true;
} else {
isSpecial = false;
isStatic = true;
String origDesc = desc;
if ((acc & AccessFlag.STATIC) == 0) {
desc = Descriptor.insertParameter(declClreplaced.getName(), origDesc);
}
acc = AccessFlag.setPackage(acc) | AccessFlag.STATIC;
mname = getAccessiblePrivate(mname, origDesc, desc, minfo, declClreplaced);
}
}
boolean popTarget = false;
if ((acc & AccessFlag.STATIC) != 0) {
if (!isStatic) {
/*
* this method is static but the target object is
* on stack. It must be popped out. If aload0pos >= 0,
* then the target object was pushed by aload_0. It is
* overwritten by NOP.
*/
isStatic = true;
if (aload0pos >= 0) {
bytecode.write(aload0pos, NOP);
} else {
popTarget = true;
}
}
bytecode.addInvokestatic(declClreplaced, mname, desc);
} else if (isSpecial) {
bytecode.addInvokespecial(targetClreplaced, mname, desc);
} else {
if (!Modifier.isPublic(declClreplaced.getModifiers()) || declClreplaced.isInterface() != targetClreplaced.isInterface()) {
declClreplaced = targetClreplaced;
}
if (declClreplaced.isInterface()) {
int nargs = Descriptor.paramSize(desc) + 1;
bytecode.addInvokeinterface(declClreplaced, mname, desc, nargs);
} else if (isStatic) {
throw new CompileError(mname + " is not static");
} else {
bytecode.addInvokevirtual(declClreplaced, mname, desc);
}
}
setReturnType(desc, isStatic, popTarget);
}
/*
* Finds (or adds if necessary) a hidden accessor if the method
* is in an enclosing clreplaced.
*
* @param desc the descriptor of the method.
*
* @param declClreplaced the clreplaced declaring the method.
*/
protected String getAccessiblePrivate(String methodName, String desc, String newDesc, MethodInfo minfo, CtClreplaced declClreplaced) throws CompileError {
if (isEnclosing(declClreplaced, thisClreplaced)) {
AccessorMaker maker = declClreplaced.getAccessorMaker();
if (maker != null) {
return maker.getMethodAccessor(methodName, desc, newDesc, minfo);
}
}
throw new CompileError("Method " + methodName + " is private");
}
/*
* Finds (or adds if necessary) a hidden constructor if the given
* constructor is in an enclosing clreplaced.
*
* @param desc the descriptor of the constructor.
*
* @param declClreplaced the clreplaced declaring the constructor.
*
* @param minfo the method info of the constructor.
*
* @return the descriptor of the hidden constructor.
*/
protected String getAccessibleConstructor(String desc, CtClreplaced declClreplaced, MethodInfo minfo) throws CompileError {
if (isEnclosing(declClreplaced, thisClreplaced)) {
AccessorMaker maker = declClreplaced.getAccessorMaker();
if (maker != null) {
return maker.getConstructor(declClreplaced, desc, minfo);
}
}
throw new CompileError("the called constructor is private in " + declClreplaced.getName());
}
private boolean isEnclosing(CtClreplaced outer, CtClreplaced inner) {
try {
while (inner != null) {
inner = inner.getDeclaringClreplaced();
if (inner == outer) {
return true;
}
}
} catch (NotFoundException e) {
}
return false;
}
public int getMethodArgsLength(ASTList args) {
return ASTList.length(args);
}
public void atMethodArgs(ASTList args, int[] types, int[] dims, String[] cnames) throws CompileError {
int i = 0;
while (args != null) {
ASTree a = args.head();
a.accept(this);
types[i] = exprType;
dims[i] = arrayDim;
cnames[i] = clreplacedName;
++i;
args = args.tail();
}
}
void setReturnType(String desc, boolean isStatic, boolean popTarget) throws CompileError {
int i = desc.indexOf(')');
if (i < 0) {
badMethod();
}
char c = desc.charAt(++i);
int dim = 0;
while (c == '[') {
++dim;
c = desc.charAt(++i);
}
arrayDim = dim;
if (c == 'L') {
int j = desc.indexOf(';', i + 1);
if (j < 0) {
badMethod();
}
exprType = CLreplaced;
clreplacedName = desc.substring(i + 1, j);
} else {
exprType = MemberResolver.descToType(c);
clreplacedName = null;
}
int etype = exprType;
if (isStatic) {
if (popTarget) {
if (is2word(etype, dim)) {
bytecode.addOpcode(DUP2_X1);
bytecode.addOpcode(POP2);
bytecode.addOpcode(POP);
} else if (etype == VOID) {
bytecode.addOpcode(POP);
} else {
bytecode.addOpcode(SWAP);
bytecode.addOpcode(POP);
}
}
}
}
@Override
protected void atFieldreplacedign(Expr expr, int op, ASTree left, ASTree right, boolean doDup) throws CompileError {
CtField f = fieldAccess(left, false);
boolean is_static = resultStatic;
if (op != '=' && !is_static) {
bytecode.addOpcode(DUP);
}
int fi;
if (op == '=') {
FieldInfo finfo = f.getFieldInfo2();
setFieldType(finfo);
AccessorMaker maker = isAccessibleField(f, finfo);
if (maker == null) {
fi = addFieldrefInfo(f, finfo);
} else {
fi = 0;
}
} else {
fi = atFieldRead(f, is_static);
}
int fType = exprType;
int fDim = arrayDim;
String cname = clreplacedName;
atreplacedignCore(expr, op, right, fType, fDim, cname);
boolean is2w = is2word(fType, fDim);
if (doDup) {
int dup_code;
if (is_static) {
dup_code = (is2w ? DUP2 : DUP);
} else {
dup_code = (is2w ? DUP2_X1 : DUP_X1);
}
bytecode.addOpcode(dup_code);
}
atFieldreplacedignCore(f, is_static, fi, is2w);
exprType = fType;
arrayDim = fDim;
clreplacedName = cname;
}
/*
* If fi == 0, the field must be a private field in an enclosing clreplaced.
*/
private void atFieldreplacedignCore(CtField f, boolean is_static, int fi, boolean is2byte) throws CompileError {
if (fi != 0) {
if (is_static) {
bytecode.add(PUTSTATIC);
bytecode.growStack(is2byte ? -2 : -1);
} else {
bytecode.add(PUTFIELD);
bytecode.growStack(is2byte ? -3 : -2);
}
bytecode.addIndex(fi);
} else {
CtClreplaced declClreplaced = f.getDeclaringClreplaced();
AccessorMaker maker = declClreplaced.getAccessorMaker();
// make should be non null.
FieldInfo finfo = f.getFieldInfo2();
MethodInfo minfo = maker.getFieldSetter(finfo, is_static);
bytecode.addInvokestatic(declClreplaced, minfo.getName(), minfo.getDescriptor());
}
}
/*
* overwritten in JvstCodeGen.
*/
@Override
public void atMember(Member mem) throws CompileError {
atFieldRead(mem);
}
@Override
protected void atFieldRead(ASTree expr) throws CompileError {
CtField f = fieldAccess(expr, true);
if (f == null) {
atArrayLength(expr);
return;
}
boolean is_static = resultStatic;
ASTree cexpr = TypeChecker.getConstantFieldValue(f);
if (cexpr == null) {
atFieldRead(f, is_static);
} else {
cexpr.accept(this);
setFieldType(f.getFieldInfo2());
}
}
private void atArrayLength(ASTree expr) throws CompileError {
if (arrayDim == 0) {
throw new CompileError(".length applied to a non array");
}
bytecode.addOpcode(ARRAYLENGTH);
exprType = INT;
arrayDim = 0;
}
/**
* Generates bytecode for reading a field value.
* It returns a fieldref_info index or zero if the field is a private
* one declared in an enclosing clreplaced.
*/
private int atFieldRead(CtField f, boolean isStatic) throws CompileError {
FieldInfo finfo = f.getFieldInfo2();
boolean is2byte = setFieldType(finfo);
AccessorMaker maker = isAccessibleField(f, finfo);
if (maker != null) {
MethodInfo minfo = maker.getFieldGetter(finfo, isStatic);
bytecode.addInvokestatic(f.getDeclaringClreplaced(), minfo.getName(), minfo.getDescriptor());
return 0;
}
int fi = addFieldrefInfo(f, finfo);
if (isStatic) {
bytecode.add(GETSTATIC);
bytecode.growStack(is2byte ? 2 : 1);
} else {
bytecode.add(GETFIELD);
bytecode.growStack(is2byte ? 1 : 0);
}
bytecode.addIndex(fi);
return fi;
}
/**
* Returns null if the field is accessible. Otherwise, it throws
* an exception or it returns AccessorMaker if the field is a private
* one declared in an enclosing clreplaced.
*/
private AccessorMaker isAccessibleField(CtField f, FieldInfo finfo) throws CompileError {
if (AccessFlag.isPrivate(finfo.getAccessFlags()) && f.getDeclaringClreplaced() != thisClreplaced) {
CtClreplaced declClreplaced = f.getDeclaringClreplaced();
if (isEnclosing(declClreplaced, thisClreplaced)) {
AccessorMaker maker = declClreplaced.getAccessorMaker();
if (maker != null) {
return maker;
}
}
throw new CompileError("Field " + f.getName() + " in " + declClreplaced.getName() + " is private.");
}
// accessible field
return null;
}
/**
* Sets exprType, arrayDim, and clreplacedName.
*
* @return true if the field type is long or double.
*/
private boolean setFieldType(FieldInfo finfo) throws CompileError {
String type = finfo.getDescriptor();
int i = 0;
int dim = 0;
char c = type.charAt(i);
while (c == '[') {
++dim;
c = type.charAt(++i);
}
arrayDim = dim;
exprType = MemberResolver.descToType(c);
if (c == 'L') {
clreplacedName = type.substring(i + 1, type.indexOf(';', i + 1));
} else {
clreplacedName = null;
}
boolean is2byte = dim == 0 && (c == 'J' || c == 'D');
return is2byte;
}
private int addFieldrefInfo(CtField f, FieldInfo finfo) {
ConstPool cp = bytecode.getConstPool();
String cname = f.getDeclaringClreplaced().getName();
int ci = cp.addClreplacedInfo(cname);
String name = finfo.getName();
String type = finfo.getDescriptor();
return cp.addFieldrefInfo(ci, name, type);
}
@Override
protected void atClreplacedObject2(String cname) throws CompileError {
if (getMajorVersion() < ClreplacedFile.JAVA_5) {
super.atClreplacedObject2(cname);
} else {
bytecode.addLdc(bytecode.getConstPool().addClreplacedInfo(cname));
}
}
@Override
protected void atFieldPlusPlus(int token, boolean isPost, ASTree oprand, Expr expr, boolean doDup) throws CompileError {
CtField f = fieldAccess(oprand, false);
boolean is_static = resultStatic;
if (!is_static) {
bytecode.addOpcode(DUP);
}
int fi = atFieldRead(f, is_static);
int t = exprType;
boolean is2w = is2word(t, arrayDim);
int dup_code;
if (is_static) {
dup_code = (is2w ? DUP2 : DUP);
} else {
dup_code = (is2w ? DUP2_X1 : DUP_X1);
}
atPlusPlusCore(dup_code, doDup, token, isPost, expr);
atFieldreplacedignCore(f, is_static, fi, is2w);
}
/*
* This method also returns a value in resultStatic.
*
* @param acceptLength true if array length is acceptable
*/
protected CtField fieldAccess(ASTree expr, boolean acceptLength) throws CompileError {
if (expr instanceof Member) {
String name = ((Member) expr).get();
CtField f = null;
try {
f = thisClreplaced.getField(name);
} catch (NotFoundException e) {
// EXPR might be part of a static member access?
throw new NoFieldException(name, expr);
}
boolean is_static = Modifier.isStatic(f.getModifiers());
if (!is_static) {
if (inStaticMethod) {
throw new CompileError("not available in a static method: " + name);
} else {
// this
bytecode.addAload(0);
}
}
resultStatic = is_static;
return f;
} else if (expr instanceof Expr) {
Expr e = (Expr) expr;
int op = e.getOperator();
if (op == MEMBER) {
/*
* static member by # (extension by Javreplacedist)
* For example, if int.clreplaced is parsed, the resulting tree
* is (# "java.lang.Integer" "TYPE").
*/
CtField f = resolver.lookupField(((Symbol) e.oprand1()).get(), (Symbol) e.oprand2());
resultStatic = true;
return f;
} else if (op == '.') {
CtField f = null;
try {
e.oprand1().accept(this);
/*
* Don't call lookupFieldByJvmName2().
* The left operand of . is not a clreplaced name but
* a normal expression.
*/
if (exprType == CLreplaced && arrayDim == 0) {
f = resolver.lookupFieldByJvmName(clreplacedName, (Symbol) e.oprand2());
} else if (acceptLength && arrayDim > 0 && ((Symbol) e.oprand2()).get().equals("length")) {
// expr is an array length.
return null;
} else {
badLvalue();
}
boolean is_static = Modifier.isStatic(f.getModifiers());
if (is_static) {
bytecode.addOpcode(POP);
}
resultStatic = is_static;
return f;
} catch (NoFieldException nfe) {
if (nfe.getExpr() != e.oprand1()) {
throw nfe;
}
/*
* EXPR should be a static field.
* If EXPR might be part of a qualified clreplaced name,
* lookupFieldByJvmName2() throws NoFieldException.
*/
Symbol fname = (Symbol) e.oprand2();
String cname = nfe.getField();
f = resolver.lookupFieldByJvmName2(cname, fname, expr);
resultStatic = true;
return f;
}
} else {
badLvalue();
}
} else {
badLvalue();
}
resultStatic = false;
// never reach
return null;
}
private static void badLvalue() throws CompileError {
throw new CompileError("bad l-value");
}
public CtClreplaced[] makeParamList(MethodDecl md) throws CompileError {
CtClreplaced[] params;
ASTList plist = md.getParams();
if (plist == null) {
params = new CtClreplaced[0];
} else {
int i = 0;
params = new CtClreplaced[plist.length()];
while (plist != null) {
params[i++] = resolver.lookupClreplaced((Declarator) plist.head());
plist = plist.tail();
}
}
return params;
}
public CtClreplaced[] makeThrowsList(MethodDecl md) throws CompileError {
CtClreplaced[] clist;
ASTList list = md.getThrows();
if (list == null) {
return null;
}
int i = 0;
clist = new CtClreplaced[list.length()];
while (list != null) {
clist[i++] = resolver.lookupClreplacedByName((ASTList) list.head());
list = list.tail();
}
return clist;
}
/*
* Converts a clreplaced name into a JVM-internal representation.
*
* It may also expand a simple clreplaced name to java.lang.*.
* For example, this converts Object into java/lang/Object.
*/
@Override
protected String resolveClreplacedName(ASTList name) throws CompileError {
return resolver.resolveClreplacedName(name);
}
/*
* Expands a simple clreplaced name to java.lang.*.
* For example, this converts Object into java/lang/Object.
*/
@Override
protected String resolveClreplacedName(String jvmName) throws CompileError {
return resolver.resolveJvmClreplacedName(jvmName);
}
}
19
Source : MemberCodeGen.java
with Apache License 2.0
from ifeilong
with Apache License 2.0
from ifeilong
private boolean isEnclosing(CtClreplaced outer, CtClreplaced inner) {
try {
while (inner != null) {
inner = inner.getDeclaringClreplaced();
if (inner == outer) {
return true;
}
}
} catch (NotFoundException e) {
}
return false;
}
19
Source : JvstTypeChecker.java
with Apache License 2.0
from ifeilong
with Apache License 2.0
from ifeilong
protected void compileUnwrapValue(CtClreplaced type) throws CompileError {
if (type == CtClreplaced.voidType) {
addNullIfVoid();
} else {
setType(type);
}
}
19
Source : JvstTypeChecker.java
with Apache License 2.0
from ifeilong
with Apache License 2.0
from ifeilong
/*
* Sets exprType, arrayDim, and clreplacedName;
* If type is void, then this method does nothing.
*/
public void setType(CtClreplaced type) throws CompileError {
setType(type, 0);
}
19
Source : JvstCodeGen.java
with Apache License 2.0
from ifeilong
with Apache License 2.0
from ifeilong
/* Code generator accepting extended Java syntax for Javreplacedist.
*/
public clreplaced JvstCodeGen extends MemberCodeGen {
String paramArrayName = null;
String paramListName = null;
CtClreplaced[] paramTypeList = null;
// variable index for $0 or $1.
private int paramVarBase = 0;
// true if $0 is used.
private boolean useParam0 = false;
// JVM name
private String param0Type = null;
public static final String sigName = "$sig";
public static final String dollarTypeName = "$type";
public static final String clazzName = "$clreplaced";
private CtClreplaced dollarType = null;
CtClreplaced returnType = null;
String returnCastName = null;
@SuppressWarnings("unused")
private String // null if $_ is not used.
returnVarName = null;
public static final String wrapperCastName = "$w";
String proceedName = null;
public static final String cflowName = "$cflow";
// null if not used.
ProceedHandler procHandler = null;
public JvstCodeGen(Bytecode b, CtClreplaced cc, ClreplacedPool cp) {
super(b, cc, cp);
setTypeChecker(new JvstTypeChecker(cc, cp, this));
}
/*
* Index of $1.
*/
private int indexOfParam1() {
return paramVarBase + (useParam0 ? 1 : 0);
}
/*
* Records a ProceedHandler obejct.
*
* @param name the name of the special method call.
* it is usually $proceed.
*/
public void setProceedHandler(ProceedHandler h, String name) {
proceedName = name;
procHandler = h;
}
/*
* If the type of the expression compiled last is void,
* add ACONST_NULL and change exprType, arrayDim, clreplacedName.
*/
public void addNullIfVoid() {
if (exprType == VOID) {
bytecode.addOpcode(ACONST_NULL);
exprType = CLreplaced;
arrayDim = 0;
clreplacedName = jvmJavaLangObject;
}
}
/*
* To support $args, $sig, and $type.
* $args is an array of parameter list.
*/
@Override
public void atMember(Member mem) throws CompileError {
String name = mem.get();
if (name.equals(paramArrayName)) {
compileParameterList(bytecode, paramTypeList, indexOfParam1());
exprType = CLreplaced;
arrayDim = 1;
clreplacedName = jvmJavaLangObject;
} else if (name.equals(sigName)) {
bytecode.addLdc(Descriptor.ofMethod(returnType, paramTypeList));
bytecode.addInvokestatic("javreplacedist/runtime/Desc", "getParams", "(Ljava/lang/String;)[Ljava/lang/Clreplaced;");
exprType = CLreplaced;
arrayDim = 1;
clreplacedName = "java/lang/Clreplaced";
} else if (name.equals(dollarTypeName)) {
if (dollarType == null) {
throw new CompileError(dollarTypeName + " is not available");
}
bytecode.addLdc(Descriptor.of(dollarType));
callGetType("getType");
} else if (name.equals(clazzName)) {
if (param0Type == null) {
throw new CompileError(clazzName + " is not available");
}
bytecode.addLdc(param0Type);
callGetType("getClazz");
} else {
super.atMember(mem);
}
}
private void callGetType(String method) {
bytecode.addInvokestatic("javreplacedist/runtime/Desc", method, "(Ljava/lang/String;)Ljava/lang/Clreplaced;");
exprType = CLreplaced;
arrayDim = 0;
clreplacedName = "java/lang/Clreplaced";
}
@Override
protected void atFieldreplacedign(Expr expr, int op, ASTree left, ASTree right, boolean doDup) throws CompileError {
if (left instanceof Member && ((Member) left).get().equals(paramArrayName)) {
if (op != '=') {
throw new CompileError("bad operator for " + paramArrayName);
}
right.accept(this);
if (arrayDim != 1 || exprType != CLreplaced) {
throw new CompileError("invalid type for " + paramArrayName);
}
atreplacedignParamList(paramTypeList, bytecode);
if (!doDup) {
bytecode.addOpcode(POP);
}
} else {
super.atFieldreplacedign(expr, op, left, right, doDup);
}
}
protected void atreplacedignParamList(CtClreplaced[] params, Bytecode code) throws CompileError {
if (params == null) {
return;
}
int varNo = indexOfParam1();
int n = params.length;
for (int i = 0; i < n; ++i) {
code.addOpcode(DUP);
code.addIconst(i);
code.addOpcode(AALOAD);
compileUnwrapValue(params[i], code);
code.addStore(varNo, params[i]);
varNo += is2word(exprType, arrayDim) ? 2 : 1;
}
}
@Override
public void atCastExpr(CastExpr expr) throws CompileError {
ASTList clreplacedname = expr.getClreplacedName();
if (clreplacedname != null && expr.getArrayDim() == 0) {
ASTree p = clreplacedname.head();
if (p instanceof Symbol && clreplacedname.tail() == null) {
String typename = ((Symbol) p).get();
if (typename.equals(returnCastName)) {
atCastToRtype(expr);
return;
} else if (typename.equals(wrapperCastName)) {
atCastToWrapper(expr);
return;
}
}
}
super.atCastExpr(expr);
}
/**
* Inserts a cast operator to the return type.
* If the return type is void, this does nothing.
*/
protected void atCastToRtype(CastExpr expr) throws CompileError {
expr.getOprand().accept(this);
if (exprType == VOID || isRefType(exprType) || arrayDim > 0) {
compileUnwrapValue(returnType, bytecode);
} else if (returnType instanceof CtPrimitiveType) {
CtPrimitiveType pt = (CtPrimitiveType) returnType;
int destType = MemberResolver.descToType(pt.getDescriptor());
atNumCastExpr(exprType, destType);
exprType = destType;
arrayDim = 0;
clreplacedName = null;
} else {
throw new CompileError("invalid cast");
}
}
protected void atCastToWrapper(CastExpr expr) throws CompileError {
expr.getOprand().accept(this);
if (isRefType(exprType) || arrayDim > 0) {
// Object type. do nothing.
return;
}
CtClreplaced clazz = resolver.lookupClreplaced(exprType, arrayDim, clreplacedName);
if (clazz instanceof CtPrimitiveType) {
CtPrimitiveType pt = (CtPrimitiveType) clazz;
String wrapper = pt.getWrapperName();
// new <wrapper>
bytecode.addNew(wrapper);
// dup
bytecode.addOpcode(DUP);
if (pt.getDataSize() > 1) {
// dup2_x2
bytecode.addOpcode(DUP2_X2);
} else {
// dup2_x1
bytecode.addOpcode(DUP2_X1);
}
// pop2
bytecode.addOpcode(POP2);
bytecode.addInvokespecial(wrapper, "<init>", "(" + pt.getDescriptor() + ")V");
// invokespecial
exprType = CLreplaced;
arrayDim = 0;
clreplacedName = jvmJavaLangObject;
}
}
/*
* Delegates to a ProcHandler object if the method call is
* $proceed(). It may process $cflow().
*/
@Override
public void atCallExpr(CallExpr expr) throws CompileError {
ASTree method = expr.oprand1();
if (method instanceof Member) {
String name = ((Member) method).get();
if (procHandler != null && name.equals(proceedName)) {
procHandler.doit(this, bytecode, (ASTList) expr.oprand2());
return;
} else if (name.equals(cflowName)) {
atCflow((ASTList) expr.oprand2());
return;
}
}
super.atCallExpr(expr);
}
/*
* To support $cflow().
*/
protected void atCflow(ASTList cname) throws CompileError {
StringBuffer sbuf = new StringBuffer();
if (cname == null || cname.tail() != null) {
throw new CompileError("bad " + cflowName);
}
makeCflowName(sbuf, cname.head());
String name = sbuf.toString();
Object[] names = resolver.getClreplacedPool().lookupCflow(name);
if (names == null) {
throw new CompileError("no such " + cflowName + ": " + name);
}
bytecode.addGetstatic((String) names[0], (String) names[1], "Ljavreplacedist/runtime/Cflow;");
bytecode.addInvokevirtual(com.feilong.lib.javreplacedist.runtime.Cflow.clreplaced.getName(), "value", "()I");
exprType = INT;
arrayDim = 0;
clreplacedName = null;
}
/*
* Syntax:
*
* <cflow> : $cflow '(' <cflow name> ')'
* <cflow name> : <identifier> ('.' <identifier>)*
*/
private static void makeCflowName(StringBuffer sbuf, ASTree name) throws CompileError {
if (name instanceof Symbol) {
sbuf.append(((Symbol) name).get());
return;
} else if (name instanceof Expr) {
Expr expr = (Expr) name;
if (expr.getOperator() == '.') {
makeCflowName(sbuf, expr.oprand1());
sbuf.append('.');
makeCflowName(sbuf, expr.oprand2());
return;
}
}
throw new CompileError("bad " + cflowName);
}
/*
* To support $$. ($$) is equivalent to ($1, ..., $n).
* It can be used only as a parameter list of method call.
*/
public boolean isParamListName(ASTList args) {
if (paramTypeList != null && args != null && args.tail() == null) {
ASTree left = args.head();
return (left instanceof Member && ((Member) left).get().equals(paramListName));
}
return false;
}
/*
* public int getMethodArgsLength(ASTList args) {
* if (!isParamListName(args))
* return super.getMethodArgsLength(args);
*
* return paramTypeList.length;
* }
*/
@Override
public int getMethodArgsLength(ASTList args) {
String pname = paramListName;
int n = 0;
while (args != null) {
ASTree a = args.head();
if (a instanceof Member && ((Member) a).get().equals(pname)) {
if (paramTypeList != null) {
n += paramTypeList.length;
}
} else {
++n;
}
args = args.tail();
}
return n;
}
@Override
public void atMethodArgs(ASTList args, int[] types, int[] dims, String[] cnames) throws CompileError {
CtClreplaced[] params = paramTypeList;
String pname = paramListName;
int i = 0;
while (args != null) {
ASTree a = args.head();
if (a instanceof Member && ((Member) a).get().equals(pname)) {
if (params != null) {
int n = params.length;
int regno = indexOfParam1();
for (int k = 0; k < n; ++k) {
CtClreplaced p = params[k];
regno += bytecode.addLoad(regno, p);
setType(p);
types[i] = exprType;
dims[i] = arrayDim;
cnames[i] = clreplacedName;
++i;
}
}
} else {
a.accept(this);
types[i] = exprType;
dims[i] = arrayDim;
cnames[i] = clreplacedName;
++i;
}
args = args.tail();
}
}
/*
* public void atMethodArgs(ASTList args, int[] types, int[] dims,
* String[] cnames) throws CompileError {
* if (!isParamListName(args)) {
* super.atMethodArgs(args, types, dims, cnames);
* return;
* }
*
* CtClreplaced[] params = paramTypeList;
* if (params == null)
* return;
*
* int n = params.length;
* int regno = indexOfParam1();
* for (int i = 0; i < n; ++i) {
* CtClreplaced p = params[i];
* regno += bytecode.addLoad(regno, p);
* setType(p);
* types[i] = exprType;
* dims[i] = arrayDim;
* cnames[i] = clreplacedName;
* }
* }
*/
/*
* called by Javac#recordSpecialProceed().
*/
void compileInvokeSpecial(ASTree target, int methodIndex, String descriptor, ASTList args) throws CompileError {
target.accept(this);
int nargs = getMethodArgsLength(args);
atMethodArgs(args, new int[nargs], new int[nargs], new String[nargs]);
bytecode.addInvokespecial(methodIndex, descriptor);
setReturnType(descriptor, false, false);
addNullIfVoid();
}
/*
* Makes it valid to write "return <expr>;" for a void method.
*/
@Override
protected void atReturnStmnt(Stmnt st) throws CompileError {
ASTree result = st.getLeft();
if (result != null && returnType == CtClreplaced.voidType) {
compileExpr(result);
if (is2word(exprType, arrayDim)) {
bytecode.addOpcode(POP2);
} else if (exprType != VOID) {
bytecode.addOpcode(POP);
}
result = null;
}
atReturnStmnt2(result);
}
/**
* Makes a cast to the return type ($r) available.
* It also enables $_.
*
* <p>
* If the return type is void, ($r) does nothing.
* The type of $_ is java.lang.Object.
*
* @param resultName
* null if $_ is not used.
* @return -1 or the variable index replacedigned to $_.
*/
public int recordReturnType(CtClreplaced type, String castName, String resultName, SymbolTable tbl) throws CompileError {
returnType = type;
returnCastName = castName;
returnVarName = resultName;
if (resultName == null) {
return -1;
}
int varNo = getMaxLocals();
int locals = varNo + recordVar(type, resultName, varNo, tbl);
setMaxLocals(locals);
return varNo;
}
/**
* Makes $type available.
*/
public void recordType(CtClreplaced t) {
dollarType = t;
}
/**
* Makes method parameters $0, $1, ..., $args, $$, and $clreplaced available.
* $0 is equivalent to THIS if the method is not static. Otherwise,
* if the method is static, then $0 is not available.
*/
public int recordParams(CtClreplaced[] params, boolean isStatic, String prefix, String paramVarName, String paramsName, SymbolTable tbl) throws CompileError {
return recordParams(params, isStatic, prefix, paramVarName, paramsName, !isStatic, 0, getThisName(), tbl);
}
/**
* Makes method parameters $0, $1, ..., $args, $$, and $clreplaced available.
* $0 is available only if use0 is true. It might not be equivalent
* to THIS.
*
* @param params
* the parameter types (the types of $1, $2, ..)
* @param prefix
* it must be "$" (the first letter of $0, $1, ...)
* @param paramVarName
* it must be "$args"
* @param paramsName
* it must be "$$"
* @param use0
* true if $0 is used.
* @param paramBase
* the register number of $0 (use0 is true)
* or $1 (otherwise).
* @param target
* the clreplaced of $0. If use0 is false, target
* can be null. The value of "target" is also used
* as the name of the type represented by $clreplaced.
* @param isStatic
* true if the method in which the compiled bytecode
* is embedded is static.
*/
public int recordParams(CtClreplaced[] params, boolean isStatic, String prefix, String paramVarName, String paramsName, boolean use0, int paramBase, String target, SymbolTable tbl) throws CompileError {
int varNo;
paramTypeList = params;
paramArrayName = paramVarName;
paramListName = paramsName;
paramVarBase = paramBase;
useParam0 = use0;
if (target != null) {
param0Type = MemberResolver.jvmToJavaName(target);
}
inStaticMethod = isStatic;
varNo = paramBase;
if (use0) {
String varName = prefix + "0";
Declarator decl = new Declarator(CLreplaced, MemberResolver.javaToJvmName(target), 0, varNo++, new Symbol(varName));
tbl.append(varName, decl);
}
for (int i = 0; i < params.length; ++i) {
varNo += recordVar(params[i], prefix + (i + 1), varNo, tbl);
}
if (getMaxLocals() < varNo) {
setMaxLocals(varNo);
}
return varNo;
}
/**
* Makes the given variable name available.
*
* @param type
* variable type
* @param varName
* variable name
*/
public int recordVariable(CtClreplaced type, String varName, SymbolTable tbl) throws CompileError {
if (varName == null) {
return -1;
}
int varNo = getMaxLocals();
int locals = varNo + recordVar(type, varName, varNo, tbl);
setMaxLocals(locals);
return varNo;
}
private int recordVar(CtClreplaced cc, String varName, int varNo, SymbolTable tbl) throws CompileError {
if (cc == CtClreplaced.voidType) {
exprType = CLreplaced;
arrayDim = 0;
clreplacedName = jvmJavaLangObject;
} else {
setType(cc);
}
Declarator decl = new Declarator(exprType, clreplacedName, arrayDim, varNo, new Symbol(varName));
tbl.append(varName, decl);
return is2word(exprType, arrayDim) ? 2 : 1;
}
/**
* Makes the given variable name available.
*
* @param typeDesc
* the type descriptor of the variable
* @param varName
* variable name
* @param varNo
* an index into the local variable array
*/
public void recordVariable(String typeDesc, String varName, int varNo, SymbolTable tbl) throws CompileError {
char c;
int dim = 0;
while ((c = typeDesc.charAt(dim)) == '[') {
++dim;
}
int type = MemberResolver.descToType(c);
String cname = null;
if (type == CLreplaced) {
if (dim == 0) {
cname = typeDesc.substring(1, typeDesc.length() - 1);
} else {
cname = typeDesc.substring(dim + 1, typeDesc.length() - 1);
}
}
Declarator decl = new Declarator(type, cname, dim, varNo, new Symbol(varName));
tbl.append(varName, decl);
}
/*
* compileParameterList() returns the stack size used
* by the produced code.
*
* This method correctly computes the max_stack value.
*
* @param regno the index of the local variable in which
* the first argument is received.
* (0: static method, 1: regular method.)
*/
public static int compileParameterList(Bytecode code, CtClreplaced[] params, int regno) {
if (params == null) {
// iconst_0
code.addIconst(0);
// anewarray Object
code.addAnewarray(javaLangObject);
return 1;
}
CtClreplaced[] args = new CtClreplaced[1];
int n = params.length;
// iconst_<n>
code.addIconst(n);
// anewarray Object
code.addAnewarray(javaLangObject);
for (int i = 0; i < n; ++i) {
// dup
code.addOpcode(Opcode.DUP);
// iconst_<i>
code.addIconst(i);
if (params[i].isPrimitive()) {
CtPrimitiveType pt = (CtPrimitiveType) params[i];
String wrapper = pt.getWrapperName();
// new <wrapper>
code.addNew(wrapper);
// dup
code.addOpcode(Opcode.DUP);
// ?load <regno>
int s = code.addLoad(regno, pt);
regno += s;
args[0] = pt;
code.addInvokespecial(wrapper, "<init>", Descriptor.ofMethod(CtClreplaced.voidType, args));
// invokespecial
} else {
// aload <regno>
code.addAload(regno);
++regno;
}
// aastore
code.addOpcode(Opcode.AASTORE);
}
return 8;
}
protected void compileUnwrapValue(CtClreplaced type, Bytecode code) throws CompileError {
if (type == CtClreplaced.voidType) {
addNullIfVoid();
return;
}
if (exprType == VOID) {
throw new CompileError("invalid type for " + returnCastName);
}
if (type instanceof CtPrimitiveType) {
CtPrimitiveType pt = (CtPrimitiveType) type;
// pt is not voidType.
String wrapper = pt.getWrapperName();
code.addCheckcast(wrapper);
code.addInvokevirtual(wrapper, pt.getGetMethodName(), pt.getGetMethodDescriptor());
setType(type);
} else {
code.addCheckcast(type);
setType(type);
}
}
/*
* Sets exprType, arrayDim, and clreplacedName;
* If type is void, then this method does nothing.
*/
public void setType(CtClreplaced type) throws CompileError {
setType(type, 0);
}
private void setType(CtClreplaced type, int dim) throws CompileError {
if (type.isPrimitive()) {
CtPrimitiveType pt = (CtPrimitiveType) type;
exprType = MemberResolver.descToType(pt.getDescriptor());
arrayDim = dim;
clreplacedName = null;
} else if (type.isArray()) {
try {
setType(type.getComponentType(), dim + 1);
} catch (NotFoundException e) {
throw new CompileError("undefined type: " + type.getName());
}
} else {
exprType = CLreplaced;
arrayDim = dim;
clreplacedName = MemberResolver.javaToJvmName(type.getName());
}
}
/*
* Performs implicit coercion from exprType to type.
*/
public void doNumCast(CtClreplaced type) throws CompileError {
if (arrayDim == 0 && !isRefType(exprType)) {
if (type instanceof CtPrimitiveType) {
CtPrimitiveType pt = (CtPrimitiveType) type;
atNumCastExpr(exprType, MemberResolver.descToType(pt.getDescriptor()));
} else {
throw new CompileError("type mismatch");
}
}
}
}
19
Source : JvstCodeGen.java
with Apache License 2.0
from ifeilong
with Apache License 2.0
from ifeilong
/**
* Makes a cast to the return type ($r) available.
* It also enables $_.
*
* <p>
* If the return type is void, ($r) does nothing.
* The type of $_ is java.lang.Object.
*
* @param resultName
* null if $_ is not used.
* @return -1 or the variable index replacedigned to $_.
*/
public int recordReturnType(CtClreplaced type, String castName, String resultName, SymbolTable tbl) throws CompileError {
returnType = type;
returnCastName = castName;
returnVarName = resultName;
if (resultName == null) {
return -1;
}
int varNo = getMaxLocals();
int locals = varNo + recordVar(type, resultName, varNo, tbl);
setMaxLocals(locals);
return varNo;
}
19
Source : JvstCodeGen.java
with Apache License 2.0
from ifeilong
with Apache License 2.0
from ifeilong
/**
* Makes $type available.
*/
public void recordType(CtClreplaced t) {
dollarType = t;
}
19
Source : JvstCodeGen.java
with Apache License 2.0
from ifeilong
with Apache License 2.0
from ifeilong
/**
* Makes method parameters $0, $1, ..., $args, $$, and $clreplaced available.
* $0 is equivalent to THIS if the method is not static. Otherwise,
* if the method is static, then $0 is not available.
*/
public int recordParams(CtClreplaced[] params, boolean isStatic, String prefix, String paramVarName, String paramsName, SymbolTable tbl) throws CompileError {
return recordParams(params, isStatic, prefix, paramVarName, paramsName, !isStatic, 0, getThisName(), tbl);
}
19
Source : JvstCodeGen.java
with Apache License 2.0
from ifeilong
with Apache License 2.0
from ifeilong
/**
* Makes the given variable name available.
*
* @param type
* variable type
* @param varName
* variable name
*/
public int recordVariable(CtClreplaced type, String varName, SymbolTable tbl) throws CompileError {
if (varName == null) {
return -1;
}
int varNo = getMaxLocals();
int locals = varNo + recordVar(type, varName, varNo, tbl);
setMaxLocals(locals);
return varNo;
}
19
Source : Javac.java
with Apache License 2.0
from ifeilong
with Apache License 2.0
from ifeilong
/**
* Prepares to use cast $r, $w, $_, and $type.
* $type is made to represent the specified return type.
* It also enables to write a return statement with a return value
* for void method.
*
* <p>
* If the return type is void, ($r) does nothing.
* The type of $_ is java.lang.Object.
*
* @param type
* the return type.
* @param useResultVar
* true if $_ is used.
* @return -1 or the variable index replacedigned to $_.
* @see #recordType(CtClreplaced)
*/
public int recordReturnType(CtClreplaced type, boolean useResultVar) throws CompileError {
gen.recordType(type);
return gen.recordReturnType(type, "$r", (useResultVar ? resultVarName : null), stable);
}
19
Source : Javac.java
with Apache License 2.0
from ifeilong
with Apache License 2.0
from ifeilong
/**
* Makes variables $0, $1, $2, ..., and $args represent method
* parameters. $args represents an array of all the parameters.
* It also makes $$ available as a parameter list of method call.
* $0 can represent a local variable other than THIS (variable 0).
* $clreplaced is also made available.
*
* <p>
* This must be called before calling <code>compileStmnt()</code> and
* <code>compileExpr()</code>. The correct value of
* <code>isStatic</code> must be recorded before compilation.
* <code>maxLocals</code> is updated to include $0,...
*
* @param use0
* true if $0 is used.
* @param varNo
* the register number of $0 (use0 is true)
* or $1 (otherwise).
* @param target
* the type of $0 (it can be null if use0 is false).
* It is used as the name of the type represented
* by $clreplaced.
* @param isStatic
* true if the method in which the compiled bytecode
* is embedded is static.
*/
public int recordParams(String target, CtClreplaced[] params, boolean use0, int varNo, boolean isStatic) throws CompileError {
return gen.recordParams(params, isStatic, "$", "$args", "$$", use0, varNo, target, stable);
}
19
Source : Javac.java
with Apache License 2.0
from ifeilong
with Apache License 2.0
from ifeilong
/**
* Makes the given variable available.
*
* @param type
* variable type
* @param name
* variable name
*/
public int recordVariable(CtClreplaced type, String name) throws CompileError {
return gen.recordVariable(type, name, stable);
}
19
Source : Javac.java
with Apache License 2.0
from ifeilong
with Apache License 2.0
from ifeilong
/**
* Prepares to use $type. Note that recordReturnType() overwrites
* the value of $type.
*
* @param t
* the type represented by $type.
*/
public void recordType(CtClreplaced t) {
gen.recordType(t);
}
19
Source : Javac.java
with Apache License 2.0
from ifeilong
with Apache License 2.0
from ifeilong
/**
* Makes variables $0 (this), $1, $2, ..., and $args represent method
* parameters. $args represents an array of all the parameters.
* It also makes $$ available as a parameter list of method call.
*
* <p>
* This must be called before calling <code>compileStmnt()</code> and
* <code>compileExpr()</code>. The correct value of
* <code>isStatic</code> must be recorded before compilation.
* <code>maxLocals</code> is updated to include $0,...
*/
public int recordParams(CtClreplaced[] params, boolean isStatic) throws CompileError {
return gen.recordParams(params, isStatic, "$", "$args", "$$", stable);
}
19
Source : AccessorMaker.java
with Apache License 2.0
from ifeilong
with Apache License 2.0
from ifeilong
/**
* AccessorMaker maintains accessors to private members of an enclosing
* clreplaced. It is necessary for compiling a method in an inner clreplaced.
*/
public clreplaced AccessorMaker {
private final CtClreplaced clazz;
private int uniqueNumber;
private final Map<String, Object> accessors;
static final String lastParamType = com.feilong.lib.javreplacedist.runtime.Inner.clreplaced.getName();
public AccessorMaker(CtClreplaced c) {
clazz = c;
uniqueNumber = 1;
accessors = new HashMap<>();
}
public String getConstructor(CtClreplaced c, String desc, MethodInfo orig) throws CompileError {
String key = "<init>:" + desc;
String consDesc = (String) accessors.get(key);
if (consDesc != null) {
// already exists.
return consDesc;
}
consDesc = Descriptor.appendParameter(lastParamType, desc);
// turn on the modified flag.
ClreplacedFile cf = clazz.getClreplacedFile();
try {
ConstPool cp = cf.getConstPool();
ClreplacedPool pool = clazz.getClreplacedPool();
MethodInfo minfo = new MethodInfo(cp, MethodInfo.nameInit, consDesc);
minfo.setAccessFlags(0);
minfo.addAttribute(new SyntheticAttribute(cp));
ExceptionsAttribute ea = orig.getExceptionsAttribute();
if (ea != null) {
minfo.addAttribute(ea.copy(cp, null));
}
CtClreplaced[] params = Descriptor.getParameterTypes(desc, pool);
Bytecode code = new Bytecode(cp);
code.addAload(0);
int regno = 1;
for (CtClreplaced param : params) {
regno += code.addLoad(regno, param);
}
// the last parameter is added.
code.setMaxLocals(regno + 1);
code.addInvokespecial(clazz, MethodInfo.nameInit, desc);
code.addReturn(null);
minfo.setCodeAttribute(code.toCodeAttribute());
cf.addMethod(minfo);
} catch (CannotCompileException e) {
throw new CompileError(e);
} catch (NotFoundException e) {
throw new CompileError(e);
}
accessors.put(key, consDesc);
return consDesc;
}
/**
* Returns the name of the method for accessing a private method.
*
* @param name
* the name of the private method.
* @param desc
* the descriptor of the private method.
* @param accDesc
* the descriptor of the accessor method. The first
* parameter type is <code>clazz</code>.
* If the private method is static,
* <code>accDesc</code> must be identical to <code>desc</code>.
*
* @param orig
* the method info of the private method.
* @return
*/
public String getMethodAccessor(String name, String desc, String accDesc, MethodInfo orig) throws CompileError {
String key = name + ":" + desc;
String accName = (String) accessors.get(key);
if (accName != null) {
// already exists.
return accName;
}
// turn on the modified flag.
ClreplacedFile cf = clazz.getClreplacedFile();
accName = findAccessorName(cf);
try {
ConstPool cp = cf.getConstPool();
ClreplacedPool pool = clazz.getClreplacedPool();
MethodInfo minfo = new MethodInfo(cp, accName, accDesc);
minfo.setAccessFlags(AccessFlag.STATIC);
minfo.addAttribute(new SyntheticAttribute(cp));
ExceptionsAttribute ea = orig.getExceptionsAttribute();
if (ea != null) {
minfo.addAttribute(ea.copy(cp, null));
}
CtClreplaced[] params = Descriptor.getParameterTypes(accDesc, pool);
int regno = 0;
Bytecode code = new Bytecode(cp);
for (CtClreplaced param : params) {
regno += code.addLoad(regno, param);
}
code.setMaxLocals(regno);
if (desc == accDesc) {
code.addInvokestatic(clazz, name, desc);
} else {
code.addInvokevirtual(clazz, name, desc);
}
code.addReturn(Descriptor.getReturnType(desc, pool));
minfo.setCodeAttribute(code.toCodeAttribute());
cf.addMethod(minfo);
} catch (CannotCompileException e) {
throw new CompileError(e);
} catch (NotFoundException e) {
throw new CompileError(e);
}
accessors.put(key, accName);
return accName;
}
/**
* Returns the method_info representing the added getter.
*/
public MethodInfo getFieldGetter(FieldInfo finfo, boolean is_static) throws CompileError {
String fieldName = finfo.getName();
String key = fieldName + ":getter";
Object res = accessors.get(key);
if (res != null) {
// already exists.
return (MethodInfo) res;
}
// turn on the modified flag.
ClreplacedFile cf = clazz.getClreplacedFile();
String accName = findAccessorName(cf);
try {
ConstPool cp = cf.getConstPool();
ClreplacedPool pool = clazz.getClreplacedPool();
String fieldType = finfo.getDescriptor();
String accDesc;
if (is_static) {
accDesc = "()" + fieldType;
} else {
accDesc = "(" + Descriptor.of(clazz) + ")" + fieldType;
}
MethodInfo minfo = new MethodInfo(cp, accName, accDesc);
minfo.setAccessFlags(AccessFlag.STATIC);
minfo.addAttribute(new SyntheticAttribute(cp));
Bytecode code = new Bytecode(cp);
if (is_static) {
code.addGetstatic(Bytecode.THIS, fieldName, fieldType);
} else {
code.addAload(0);
code.addGetfield(Bytecode.THIS, fieldName, fieldType);
code.setMaxLocals(1);
}
code.addReturn(Descriptor.toCtClreplaced(fieldType, pool));
minfo.setCodeAttribute(code.toCodeAttribute());
cf.addMethod(minfo);
accessors.put(key, minfo);
return minfo;
} catch (CannotCompileException e) {
throw new CompileError(e);
} catch (NotFoundException e) {
throw new CompileError(e);
}
}
/**
* Returns the method_info representing the added setter.
*/
public MethodInfo getFieldSetter(FieldInfo finfo, boolean is_static) throws CompileError {
String fieldName = finfo.getName();
String key = fieldName + ":setter";
Object res = accessors.get(key);
if (res != null) {
// already exists.
return (MethodInfo) res;
}
// turn on the modified flag.
ClreplacedFile cf = clazz.getClreplacedFile();
String accName = findAccessorName(cf);
try {
ConstPool cp = cf.getConstPool();
ClreplacedPool pool = clazz.getClreplacedPool();
String fieldType = finfo.getDescriptor();
String accDesc;
if (is_static) {
accDesc = "(" + fieldType + ")V";
} else {
accDesc = "(" + Descriptor.of(clazz) + fieldType + ")V";
}
MethodInfo minfo = new MethodInfo(cp, accName, accDesc);
minfo.setAccessFlags(AccessFlag.STATIC);
minfo.addAttribute(new SyntheticAttribute(cp));
Bytecode code = new Bytecode(cp);
int reg;
if (is_static) {
reg = code.addLoad(0, Descriptor.toCtClreplaced(fieldType, pool));
code.addPutstatic(Bytecode.THIS, fieldName, fieldType);
} else {
code.addAload(0);
reg = code.addLoad(1, Descriptor.toCtClreplaced(fieldType, pool)) + 1;
code.addPutfield(Bytecode.THIS, fieldName, fieldType);
}
code.addReturn(null);
code.setMaxLocals(reg);
minfo.setCodeAttribute(code.toCodeAttribute());
cf.addMethod(minfo);
accessors.put(key, minfo);
return minfo;
} catch (CannotCompileException e) {
throw new CompileError(e);
} catch (NotFoundException e) {
throw new CompileError(e);
}
}
private String findAccessorName(ClreplacedFile cf) {
String accName;
do {
accName = "access$" + uniqueNumber++;
} while (cf.getMethod(accName) != null);
return accName;
}
}
19
Source : TypeData.java
with Apache License 2.0
from ifeilong
with Apache License 2.0
from ifeilong
static boolean eq(CtClreplaced one, CtClreplaced two) {
return one == two || (one != null && two != null && one.getName().equals(two.getName()));
}
19
Source : TypeData.java
with Apache License 2.0
from ifeilong
with Apache License 2.0
from ifeilong
/**
* Finds the most specific common super clreplaced of the given clreplacedes
* by considering array types.
*/
public static CtClreplaced commonSuperClreplacedEx(CtClreplaced one, CtClreplaced two) throws NotFoundException {
if (one == two) {
return one;
} else if (one.isArray() && two.isArray()) {
CtClreplaced ele1 = one.getComponentType();
CtClreplaced ele2 = two.getComponentType();
CtClreplaced element = commonSuperClreplacedEx(ele1, ele2);
if (element == ele1) {
return one;
} else if (element == ele2) {
return two;
} else {
return one.getClreplacedPool().get(element == null ? "java.lang.Object" : element.getName() + "[]");
}
} else if (one.isPrimitive() || two.isPrimitive()) {
// TOP
return null;
} else if (one.isArray() || two.isArray()) {
return one.getClreplacedPool().get("java.lang.Object");
} else {
return commonSuperClreplaced(one, two);
}
}
19
Source : Descriptor.java
with Apache License 2.0
from ifeilong
with Apache License 2.0
from ifeilong
/**
* Returns a <code>CtClreplaced</code> object representing the type
* specified by the given descriptor.
*
* <p>
* This method works even if the package-clreplaced separator is
* not <code>/</code> but <code>.</code> (period). For example,
* it accepts <code>Ljava.lang.Object;</code>
* as well as <code>Ljava/lang/Object;</code>.
*
* @param desc
* descriptor.
* @param cp
* the clreplaced pool used for obtaining
* a <code>CtClreplaced</code> object.
*/
public static CtClreplaced toCtClreplaced(String desc, ClreplacedPool cp) throws NotFoundException {
CtClreplaced[] clazz = new CtClreplaced[1];
int res = toCtClreplaced(cp, desc, 0, clazz, 0);
if (res >= 0) {
return clazz[0];
}
// maybe, you forgot to surround the clreplaced name with
// L and ;. It violates the protocol, but I'm tolerant...
return cp.get(desc.replace('/', '.'));
}
19
Source : Descriptor.java
with Apache License 2.0
from ifeilong
with Apache License 2.0
from ifeilong
static CtClreplaced toPrimitiveClreplaced(char c) {
CtClreplaced type = null;
switch(c) {
case 'Z':
type = CtClreplaced.booleanType;
break;
case 'C':
type = CtClreplaced.charType;
break;
case 'B':
type = CtClreplaced.byteType;
break;
case 'S':
type = CtClreplaced.shortType;
break;
case 'I':
type = CtClreplaced.intType;
break;
case 'J':
type = CtClreplaced.longType;
break;
case 'F':
type = CtClreplaced.floatType;
break;
case 'D':
type = CtClreplaced.doubleType;
break;
case 'V':
type = CtClreplaced.voidType;
break;
}
return type;
}
19
Source : Descriptor.java
with Apache License 2.0
from ifeilong
with Apache License 2.0
from ifeilong
/**
* Inserts a parameter type at the beginning of the parameter
* list represented
* by the given descriptor.
*
* @param type
* the type of the inserted parameter.
* @param descriptor
* the descriptor of the method.
*/
public static String insertParameter(CtClreplaced type, String descriptor) {
if (descriptor.charAt(0) != '(') {
return descriptor;
}
return "(" + of(type) + descriptor.substring(1);
}
19
Source : Descriptor.java
with Apache License 2.0
from ifeilong
with Apache License 2.0
from ifeilong
/**
* Returns the <code>CtClreplaced</code> objects representing the parameter
* types specified by the given descriptor.
*
* @param desc
* descriptor
* @param cp
* the clreplaced pool used for obtaining
* a <code>CtClreplaced</code> object.
*/
public static CtClreplaced[] getParameterTypes(String desc, ClreplacedPool cp) throws NotFoundException {
if (desc.charAt(0) != '(') {
return null;
}
int num = numOfParameters(desc);
CtClreplaced[] args = new CtClreplaced[num];
int n = 0;
int i = 1;
do {
i = toCtClreplaced(cp, desc, i, args, n++);
} while (i > 0);
return args;
}
19
Source : Descriptor.java
with Apache License 2.0
from ifeilong
with Apache License 2.0
from ifeilong
/**
* Returns the descriptor representing a list of parameter types.
* For example, if the given parameter types are two <code>int</code>,
* then this method returns <code>"(II)"</code>.
*
* @param paramTypes
* parameter types
*/
public static String ofParameters(CtClreplaced[] paramTypes) {
return ofMethod(null, paramTypes);
}
19
Source : Descriptor.java
with Apache License 2.0
from ifeilong
with Apache License 2.0
from ifeilong
/**
* Returns the descriptor representing a method that receives
* the given parameter types and returns the given type.
*
* @param returnType
* return type
* @param paramTypes
* parameter types
*/
public static String ofMethod(CtClreplaced returnType, CtClreplaced[] paramTypes) {
StringBuffer desc = new StringBuffer();
desc.append('(');
if (paramTypes != null) {
int n = paramTypes.length;
for (int i = 0; i < n; ++i) {
toDescriptor(desc, paramTypes[i]);
}
}
desc.append(')');
if (returnType != null) {
toDescriptor(desc, returnType);
}
return desc.toString();
}
19
Source : Descriptor.java
with Apache License 2.0
from ifeilong
with Apache License 2.0
from ifeilong
/**
* Returns the descriptor representing a constructor receiving
* the given parameter types.
*
* @param paramTypes
* parameter types
*/
public static String ofConstructor(CtClreplaced[] paramTypes) {
return ofMethod(CtClreplaced.voidType, paramTypes);
}
19
Source : Descriptor.java
with Apache License 2.0
from ifeilong
with Apache License 2.0
from ifeilong
/**
* Returns the <code>CtClreplaced</code> object representing the return
* type specified by the given descriptor.
*
* @param desc
* descriptor
* @param cp
* the clreplaced pool used for obtaining
* a <code>CtClreplaced</code> object.
*/
public static CtClreplaced getReturnType(String desc, ClreplacedPool cp) throws NotFoundException {
int i = desc.indexOf(')');
if (i < 0) {
return null;
}
CtClreplaced[] type = new CtClreplaced[1];
toCtClreplaced(cp, desc, i + 1, type, 0);
return type[0];
}
19
Source : Descriptor.java
with Apache License 2.0
from ifeilong
with Apache License 2.0
from ifeilong
private static int toCtClreplaced(ClreplacedPool cp, String desc, int i, CtClreplaced[] args, int n) throws NotFoundException {
int i2;
String name;
int arrayDim = 0;
char c = desc.charAt(i);
while (c == '[') {
++arrayDim;
c = desc.charAt(++i);
}
if (c == 'L') {
i2 = desc.indexOf(';', ++i);
name = desc.substring(i, i2++).replace('/', '.');
} else {
CtClreplaced type = toPrimitiveClreplaced(c);
if (type == null) {
// error
return -1;
}
i2 = i + 1;
if (arrayDim == 0) {
args[n] = type;
// neither an array type or a clreplaced type
return i2;
}
name = type.getName();
}
if (arrayDim > 0) {
StringBuffer sbuf = new StringBuffer(name);
while (arrayDim-- > 0) {
sbuf.append("[]");
}
name = sbuf.toString();
}
args[n] = cp.get(name);
return i2;
}
19
Source : Descriptor.java
with Apache License 2.0
from ifeilong
with Apache License 2.0
from ifeilong
/**
* Appends a parameter type to the parameter list represented
* by the given descriptor. The appended parameter becomes
* the last parameter.
*
* @param type
* the type of the appended parameter.
* @param descriptor
* the original descriptor.
*/
public static String appendParameter(CtClreplaced type, String descriptor) {
int i = descriptor.indexOf(')');
if (i < 0) {
return descriptor;
}
StringBuffer newdesc = new StringBuffer();
newdesc.append(descriptor.substring(0, i));
toDescriptor(newdesc, type);
newdesc.append(descriptor.substring(i));
return newdesc.toString();
}
19
Source : Descriptor.java
with Apache License 2.0
from ifeilong
with Apache License 2.0
from ifeilong
/**
* Returns the descriptor representing the given type.
*/
public static String of(CtClreplaced type) {
StringBuffer sbuf = new StringBuffer();
toDescriptor(sbuf, type);
return sbuf.toString();
}
19
Source : Bytecode.java
with Apache License 2.0
from ifeilong
with Apache License 2.0
from ifeilong
/**
* A utility clreplaced for producing a bytecode sequence.
*
* <p>
* A <code>Bytecode</code> object is an unbounded array
* containing bytecode. For example,
*
* <pre>
* ConstPool cp = ...; // constant pool table
* Bytecode b = new Bytecode(cp, 1, 0);
* b.addIconst(3);
* b.addReturn(CtClreplaced.intType);
* CodeAttribute ca = b.toCodeAttribute();
* </pre>
*
* <p>
* This program produces a Code attribute including a bytecode
* sequence:
*
* <pre>
* iconst_3
* ireturn
* </pre>
*
* @see ConstPool
* @see CodeAttribute
*/
public clreplaced Bytecode extends ByteVector implements Cloneable, Opcode {
/**
* Represents the <code>CtClreplaced</code> file using the
* constant pool table given to this <code>Bytecode</code> object.
*/
public static final CtClreplaced THIS = ConstPool.THIS;
ConstPool constPool;
int maxStack, maxLocals;
ExceptionTable tryblocks;
private int stackDepth;
/**
* Constructs a <code>Bytecode</code> object with an empty bytecode
* sequence.
*
* <p>
* The parameters <code>stacksize</code> and <code>localvars</code>
* specify initial values
* of <code>max_stack</code> and <code>max_locals</code>.
* They can be changed later.
*
* @param cp
* constant pool table.
* @param stacksize
* <code>max_stack</code>.
* @param localvars
* <code>max_locals</code>.
*/
public Bytecode(ConstPool cp, int stacksize, int localvars) {
constPool = cp;
maxStack = stacksize;
maxLocals = localvars;
tryblocks = new ExceptionTable(cp);
stackDepth = 0;
}
/**
* Constructs a <code>Bytecode</code> object with an empty bytecode
* sequence. The initial values of <code>max_stack</code> and
* <code>max_locals</code> are zero.
*
* @param cp
* constant pool table.
* @see Bytecode#setMaxStack(int)
* @see Bytecode#setMaxLocals(int)
*/
public Bytecode(ConstPool cp) {
this(cp, 0, 0);
}
/**
* Creates and returns a copy of this object.
* The constant pool object is shared between this object
* and the cloned object.
*/
@Override
public Object clone() {
try {
Bytecode bc = (Bytecode) super.clone();
bc.tryblocks = (ExceptionTable) tryblocks.clone();
return bc;
} catch (CloneNotSupportedException cnse) {
throw new RuntimeException(cnse);
}
}
/**
* Gets a constant pool table.
*/
public ConstPool getConstPool() {
return constPool;
}
/**
* Returns <code>exception_table</code>.
*/
public ExceptionTable getExceptionTable() {
return tryblocks;
}
/**
* Converts to a <code>CodeAttribute</code>.
*/
public CodeAttribute toCodeAttribute() {
return new CodeAttribute(constPool, maxStack, maxLocals, get(), tryblocks);
}
/**
* Returns the length of the bytecode sequence.
*/
public int length() {
return getSize();
}
/**
* Returns the produced bytecode sequence.
*/
public byte[] get() {
return copy();
}
/**
* Gets <code>max_stack</code>.
*/
public int getMaxStack() {
return maxStack;
}
/**
* Sets <code>max_stack</code>.
*
* <p>
* This value may be automatically updated when an instruction
* is appended. A <code>Bytecode</code> object maintains the current
* stack depth whenever an instruction is added
* by <code>addOpcode()</code>. For example, if DUP is appended,
* the current stack depth is increased by one. If the new stack
* depth is more than <code>max_stack</code>, then it is replacedigned
* to <code>max_stack</code>. However, if branch instructions are
* appended, the current stack depth may not be correctly maintained.
*
* @see #addOpcode(int)
*/
public void setMaxStack(int size) {
maxStack = size;
}
/**
* Gets <code>max_locals</code>.
*/
public int getMaxLocals() {
return maxLocals;
}
/**
* Sets <code>max_locals</code>.
*/
public void setMaxLocals(int size) {
maxLocals = size;
}
/**
* Sets <code>max_locals</code>.
*
* <p>
* This computes the number of local variables
* used to preplaced method parameters and sets <code>max_locals</code>
* to that number plus <code>locals</code>.
*
* @param isStatic
* true if <code>params</code> must be
* interpreted as parameters to a static method.
* @param params
* parameter types.
* @param locals
* the number of local variables excluding
* ones used to preplaced parameters.
*/
public void setMaxLocals(boolean isStatic, CtClreplaced[] params, int locals) {
if (!isStatic) {
++locals;
}
if (params != null) {
CtClreplaced doubleType = CtClreplaced.doubleType;
CtClreplaced longType = CtClreplaced.longType;
int n = params.length;
for (int i = 0; i < n; ++i) {
CtClreplaced type = params[i];
if (type == doubleType || type == longType) {
locals += 2;
} else {
++locals;
}
}
}
maxLocals = locals;
}
/**
* Increments <code>max_locals</code>.
*/
public void incMaxLocals(int diff) {
maxLocals += diff;
}
/**
* Adds a new entry of <code>exception_table</code>.
*/
public void addExceptionHandler(int start, int end, int handler, CtClreplaced type) {
addExceptionHandler(start, end, handler, constPool.addClreplacedInfo(type));
}
/**
* Adds a new entry of <code>exception_table</code>.
*
* @param type
* the fully-qualified name of a throwable clreplaced.
*/
public void addExceptionHandler(int start, int end, int handler, String type) {
addExceptionHandler(start, end, handler, constPool.addClreplacedInfo(type));
}
/**
* Adds a new entry of <code>exception_table</code>.
*/
public void addExceptionHandler(int start, int end, int handler, int type) {
tryblocks.add(start, end, handler, type);
}
/**
* Returns the length of bytecode sequence
* that have been added so far.
*/
public int currentPc() {
return getSize();
}
/**
* Reads a signed 8bit value at the offset from the beginning of the
* bytecode sequence.
*
* @throws ArrayIndexOutOfBoundsException
* if offset is invalid.
*/
@Override
public int read(int offset) {
return super.read(offset);
}
/**
* Reads a signed 16bit value at the offset from the beginning of the
* bytecode sequence.
*/
public int read16bit(int offset) {
int v1 = read(offset);
int v2 = read(offset + 1);
return (v1 << 8) + (v2 & 0xff);
}
/**
* Reads a signed 32bit value at the offset from the beginning of the
* bytecode sequence.
*/
public int read32bit(int offset) {
int v1 = read16bit(offset);
int v2 = read16bit(offset + 2);
return (v1 << 16) + (v2 & 0xffff);
}
/**
* Writes an 8bit value at the offset from the beginning of the
* bytecode sequence.
*
* @throws ArrayIndexOutOfBoundsException
* if offset is invalid.
*/
@Override
public void write(int offset, int value) {
super.write(offset, value);
}
/**
* Writes an 16bit value at the offset from the beginning of the
* bytecode sequence.
*/
public void write16bit(int offset, int value) {
write(offset, value >> 8);
write(offset + 1, value);
}
/**
* Writes an 32bit value at the offset from the beginning of the
* bytecode sequence.
*/
public void write32bit(int offset, int value) {
write16bit(offset, value >> 16);
write16bit(offset + 2, value);
}
/**
* Appends an 8bit value to the end of the bytecode sequence.
*/
@Override
public void add(int code) {
super.add(code);
}
/**
* Appends a 32bit value to the end of the bytecode sequence.
*/
public void add32bit(int value) {
add(value >> 24, value >> 16, value >> 8, value);
}
/**
* Appends the length-byte gap to the end of the bytecode sequence.
*
* @param length
* the gap length in byte.
*/
@Override
public void addGap(int length) {
super.addGap(length);
}
/**
* Appends an 8bit opcode to the end of the bytecode sequence.
* The current stack depth is updated.
* <code>max_stack</code> is updated if the current stack depth
* is the deepest so far.
*
* <p>
* Note: some instructions such as INVOKEVIRTUAL does not
* update the current stack depth since the increment depends
* on the method signature.
* <code>growStack()</code> must be explicitly called.
*/
public void addOpcode(int code) {
add(code);
growStack(STACK_GROW[code]);
}
/**
* Increases the current stack depth.
* It also updates <code>max_stack</code> if the current stack depth
* is the deepest so far.
*
* @param diff
* the number added to the current stack depth.
*/
public void growStack(int diff) {
setStackDepth(stackDepth + diff);
}
/**
* Returns the current stack depth.
*/
public int getStackDepth() {
return stackDepth;
}
/**
* Sets the current stack depth.
* It also updates <code>max_stack</code> if the current stack depth
* is the deepest so far.
*
* @param depth
* new value.
*/
public void setStackDepth(int depth) {
stackDepth = depth;
if (stackDepth > maxStack) {
maxStack = stackDepth;
}
}
/**
* Appends a 16bit value to the end of the bytecode sequence.
* It never changes the current stack depth.
*/
public void addIndex(int index) {
add(index >> 8, index);
}
/**
* Appends ALOAD or (WIDE) ALOAD_<n>
*
* @param n
* an index into the local variable array.
*/
public void addAload(int n) {
if (n < 4) {
// aload_<n>
addOpcode(42 + n);
} else if (n < 0x100) {
// aload
addOpcode(ALOAD);
add(n);
} else {
addOpcode(WIDE);
addOpcode(ALOAD);
addIndex(n);
}
}
/**
* Appends ASTORE or (WIDE) ASTORE_<n>
*
* @param n
* an index into the local variable array.
*/
public void addAstore(int n) {
if (n < 4) {
// astore_<n>
addOpcode(75 + n);
} else if (n < 0x100) {
// astore
addOpcode(ASTORE);
add(n);
} else {
addOpcode(WIDE);
addOpcode(ASTORE);
addIndex(n);
}
}
/**
* Appends ICONST or ICONST_<n>
*
* @param n
* the pushed integer constant.
*/
public void addIconst(int n) {
if (n < 6 && -2 < n) {
// iconst_<i> -1..5
addOpcode(3 + n);
} else if (n <= 127 && -128 <= n) {
// bipush
addOpcode(16);
add(n);
} else if (n <= 32767 && -32768 <= n) {
// sipush
addOpcode(17);
add(n >> 8);
add(n);
} else {
addLdc(constPool.addIntegerInfo(n));
}
}
/**
* Appends an instruction for pushing zero or null on the stack.
* If the type is void, this method does not append any instruction.
*
* @param type
* the type of the zero value (or null).
*/
public void addConstZero(CtClreplaced type) {
if (type.isPrimitive()) {
if (type == CtClreplaced.longType) {
addOpcode(LCONST_0);
} else if (type == CtClreplaced.floatType) {
addOpcode(FCONST_0);
} else if (type == CtClreplaced.doubleType) {
addOpcode(DCONST_0);
} else if (type == CtClreplaced.voidType) {
throw new RuntimeException("void type?");
} else {
addOpcode(ICONST_0);
}
} else {
addOpcode(ACONST_NULL);
}
}
/**
* Appends ILOAD or (WIDE) ILOAD_<n>
*
* @param n
* an index into the local variable array.
*/
public void addIload(int n) {
if (n < 4) {
// iload_<n>
addOpcode(26 + n);
} else if (n < 0x100) {
// iload
addOpcode(ILOAD);
add(n);
} else {
addOpcode(WIDE);
addOpcode(ILOAD);
addIndex(n);
}
}
/**
* Appends ISTORE or (WIDE) ISTORE_<n>
*
* @param n
* an index into the local variable array.
*/
public void addIstore(int n) {
if (n < 4) {
// istore_<n>
addOpcode(59 + n);
} else if (n < 0x100) {
// istore
addOpcode(ISTORE);
add(n);
} else {
addOpcode(WIDE);
addOpcode(ISTORE);
addIndex(n);
}
}
/**
* Appends LCONST or LCONST_<n>
*
* @param n
* the pushed long integer constant.
*/
public void addLconst(long n) {
if (n == 0 || n == 1) {
// lconst_<n>
addOpcode(9 + (int) n);
} else {
addLdc2w(n);
}
}
/**
* Appends LLOAD or (WIDE) LLOAD_<n>
*
* @param n
* an index into the local variable array.
*/
public void addLload(int n) {
if (n < 4) {
// lload_<n>
addOpcode(30 + n);
} else if (n < 0x100) {
// lload
addOpcode(LLOAD);
add(n);
} else {
addOpcode(WIDE);
addOpcode(LLOAD);
addIndex(n);
}
}
/**
* Appends LSTORE or LSTORE_<n>
*
* @param n
* an index into the local variable array.
*/
public void addLstore(int n) {
if (n < 4) {
// lstore_<n>
addOpcode(63 + n);
} else if (n < 0x100) {
// lstore
addOpcode(LSTORE);
add(n);
} else {
addOpcode(WIDE);
addOpcode(LSTORE);
addIndex(n);
}
}
/**
* Appends DCONST or DCONST_<n>
*
* @param d
* the pushed double constant.
*/
public void addDconst(double d) {
if (d == 0.0 || d == 1.0) {
// dconst_<n>
addOpcode(14 + (int) d);
} else {
addLdc2w(d);
}
}
/**
* Appends DLOAD or (WIDE) DLOAD_<n>
*
* @param n
* an index into the local variable array.
*/
public void addDload(int n) {
if (n < 4) {
// dload_<n>
addOpcode(38 + n);
} else if (n < 0x100) {
// dload
addOpcode(DLOAD);
add(n);
} else {
addOpcode(WIDE);
addOpcode(DLOAD);
addIndex(n);
}
}
/**
* Appends DSTORE or (WIDE) DSTORE_<n>
*
* @param n
* an index into the local variable array.
*/
public void addDstore(int n) {
if (n < 4) {
// dstore_<n>
addOpcode(71 + n);
} else if (n < 0x100) {
// dstore
addOpcode(DSTORE);
add(n);
} else {
addOpcode(WIDE);
addOpcode(DSTORE);
addIndex(n);
}
}
/**
* Appends FCONST or FCONST_<n>
*
* @param f
* the pushed float constant.
*/
public void addFconst(float f) {
if (f == 0.0f || f == 1.0f || f == 2.0f) {
// fconst_<n>
addOpcode(11 + (int) f);
} else {
addLdc(constPool.addFloatInfo(f));
}
}
/**
* Appends FLOAD or (WIDE) FLOAD_<n>
*
* @param n
* an index into the local variable array.
*/
public void addFload(int n) {
if (n < 4) {
// fload_<n>
addOpcode(34 + n);
} else if (n < 0x100) {
// fload
addOpcode(FLOAD);
add(n);
} else {
addOpcode(WIDE);
addOpcode(FLOAD);
addIndex(n);
}
}
/**
* Appends FSTORE or FSTORE_<n>
*
* @param n
* an index into the local variable array.
*/
public void addFstore(int n) {
if (n < 4) {
// fstore_<n>
addOpcode(67 + n);
} else if (n < 0x100) {
// fstore
addOpcode(FSTORE);
add(n);
} else {
addOpcode(WIDE);
addOpcode(FSTORE);
addIndex(n);
}
}
/**
* Appends an instruction for loading a value from the
* local variable at the index <code>n</code>.
*
* @param n
* the index.
* @param type
* the type of the loaded value.
* @return the size of the value (1 or 2 word).
*/
public int addLoad(int n, CtClreplaced type) {
if (type.isPrimitive()) {
if (type == CtClreplaced.booleanType || type == CtClreplaced.charType || type == CtClreplaced.byteType || type == CtClreplaced.shortType || type == CtClreplaced.intType) {
addIload(n);
} else if (type == CtClreplaced.longType) {
addLload(n);
return 2;
} else if (type == CtClreplaced.floatType) {
addFload(n);
} else if (type == CtClreplaced.doubleType) {
addDload(n);
return 2;
} else {
throw new RuntimeException("void type?");
}
} else {
addAload(n);
}
return 1;
}
/**
* Appends an instruction for storing a value into the
* local variable at the index <code>n</code>.
*
* @param n
* the index.
* @param type
* the type of the stored value.
* @return 2 if the type is long or double. Otherwise 1.
*/
public int addStore(int n, CtClreplaced type) {
if (type.isPrimitive()) {
if (type == CtClreplaced.booleanType || type == CtClreplaced.charType || type == CtClreplaced.byteType || type == CtClreplaced.shortType || type == CtClreplaced.intType) {
addIstore(n);
} else if (type == CtClreplaced.longType) {
addLstore(n);
return 2;
} else if (type == CtClreplaced.floatType) {
addFstore(n);
} else if (type == CtClreplaced.doubleType) {
addDstore(n);
return 2;
} else {
throw new RuntimeException("void type?");
}
} else {
addAstore(n);
}
return 1;
}
/**
* Appends instructions for loading all the parameters onto the
* operand stack.
*
* @param offset
* the index of the first parameter. It is 0
* if the method is static. Otherwise, it is 1.
*/
public int addLoadParameters(CtClreplaced[] params, int offset) {
int stacksize = 0;
if (params != null) {
int n = params.length;
for (int i = 0; i < n; ++i) {
stacksize += addLoad(stacksize + offset, params[i]);
}
}
return stacksize;
}
/**
* Appends CHECKCAST.
*
* @param c
* the type.
*/
public void addCheckcast(CtClreplaced c) {
addOpcode(CHECKCAST);
addIndex(constPool.addClreplacedInfo(c));
}
/**
* Appends CHECKCAST.
*
* @param clreplacedname
* a fully-qualified clreplaced name.
*/
public void addCheckcast(String clreplacedname) {
addOpcode(CHECKCAST);
addIndex(constPool.addClreplacedInfo(clreplacedname));
}
/**
* Appends INSTANCEOF.
*
* @param clreplacedname
* the clreplaced name.
*/
public void addInstanceof(String clreplacedname) {
addOpcode(INSTANCEOF);
addIndex(constPool.addClreplacedInfo(clreplacedname));
}
/**
* Appends GETFIELD.
*
* @param c
* the clreplaced.
* @param name
* the field name.
* @param type
* the descriptor of the field type.
*
* @see Descriptor#of(CtClreplaced)
*/
public void addGetfield(CtClreplaced c, String name, String type) {
add(GETFIELD);
int ci = constPool.addClreplacedInfo(c);
addIndex(constPool.addFieldrefInfo(ci, name, type));
growStack(Descriptor.dataSize(type) - 1);
}
/**
* Appends GETFIELD.
*
* @param c
* the fully-qualified clreplaced name.
* @param name
* the field name.
* @param type
* the descriptor of the field type.
*
* @see Descriptor#of(CtClreplaced)
*/
public void addGetfield(String c, String name, String type) {
add(GETFIELD);
int ci = constPool.addClreplacedInfo(c);
addIndex(constPool.addFieldrefInfo(ci, name, type));
growStack(Descriptor.dataSize(type) - 1);
}
/**
* Appends GETSTATIC.
*
* @param c
* the clreplaced
* @param name
* the field name
* @param type
* the descriptor of the field type.
*
* @see Descriptor#of(CtClreplaced)
*/
public void addGetstatic(CtClreplaced c, String name, String type) {
add(GETSTATIC);
int ci = constPool.addClreplacedInfo(c);
addIndex(constPool.addFieldrefInfo(ci, name, type));
growStack(Descriptor.dataSize(type));
}
/**
* Appends GETSTATIC.
*
* @param c
* the fully-qualified clreplaced name
* @param name
* the field name
* @param type
* the descriptor of the field type.
*
* @see Descriptor#of(CtClreplaced)
*/
public void addGetstatic(String c, String name, String type) {
add(GETSTATIC);
int ci = constPool.addClreplacedInfo(c);
addIndex(constPool.addFieldrefInfo(ci, name, type));
growStack(Descriptor.dataSize(type));
}
/**
* Appends INVOKESPECIAL.
*
* @param clazz
* the target clreplaced.
* @param name
* the method name.
* @param returnType
* the return type.
* @param paramTypes
* the parameter types.
*/
public void addInvokespecial(CtClreplaced clazz, String name, CtClreplaced returnType, CtClreplaced[] paramTypes) {
String desc = Descriptor.ofMethod(returnType, paramTypes);
addInvokespecial(clazz, name, desc);
}
/**
* Appends INVOKESPECIAL.
*
* @param clazz
* the target clreplaced.
* @param name
* the method name
* @param desc
* the descriptor of the method signature.
*
* @see Descriptor#ofMethod(CtClreplaced,CtClreplaced[])
* @see Descriptor#ofConstructor(CtClreplaced[])
*/
public void addInvokespecial(CtClreplaced clazz, String name, String desc) {
boolean isInterface = clazz == null ? false : clazz.isInterface();
addInvokespecial(isInterface, constPool.addClreplacedInfo(clazz), name, desc);
}
/**
* Appends INVOKESPECIAL. The invoked method must not be a default
* method declared in an interface.
*
* @param clazz
* the fully-qualified clreplaced name.
* @param name
* the method name
* @param desc
* the descriptor of the method signature.
*
* @see Descriptor#ofMethod(CtClreplaced,CtClreplaced[])
* @see Descriptor#ofConstructor(CtClreplaced[])
*/
public void addInvokespecial(String clazz, String name, String desc) {
addInvokespecial(false, constPool.addClreplacedInfo(clazz), name, desc);
}
/**
* Appends INVOKESPECIAL. The invoked method must not be a default
* method declared in an interface.
*
* @param clazz
* the index of <code>CONSTANT_Clreplaced_info</code>
* structure.
* @param name
* the method name
* @param desc
* the descriptor of the method signature.
*
* @see Descriptor#ofMethod(CtClreplaced,CtClreplaced[])
* @see Descriptor#ofConstructor(CtClreplaced[])
*/
public void addInvokespecial(int clazz, String name, String desc) {
addInvokespecial(false, clazz, name, desc);
}
/**
* Appends INVOKESPECIAL.
*
* @param isInterface
* true if the invoked method is a default method
* declared in an interface.
* @param clazz
* the index of <code>CONSTANT_Clreplaced_info</code>
* structure.
* @param name
* the method name
* @param desc
* the descriptor of the method signature.
*
* @see Descriptor#ofMethod(CtClreplaced,CtClreplaced[])
* @see Descriptor#ofConstructor(CtClreplaced[])
*/
public void addInvokespecial(boolean isInterface, int clazz, String name, String desc) {
int index;
if (isInterface) {
index = constPool.addInterfaceMethodrefInfo(clazz, name, desc);
} else {
index = constPool.addMethodrefInfo(clazz, name, desc);
}
addInvokespecial(index, desc);
}
/**
* Appends INVOKESPECIAL.
*
* @param index
* the index of <code>CONSTANT_Methodref_info</code>
* or <code>CONSTANT_InterfaceMethodref_info</code>
* @param desc
* the descriptor of the method signature.
*
* @see Descriptor#ofMethod(CtClreplaced,CtClreplaced[])
* @see Descriptor#ofConstructor(CtClreplaced[])
*/
public void addInvokespecial(int index, String desc) {
add(INVOKESPECIAL);
addIndex(index);
growStack(Descriptor.dataSize(desc) - 1);
}
/**
* Appends INVOKESTATIC.
*
* @param clazz
* the target clreplaced.
* @param name
* the method name
* @param returnType
* the return type.
* @param paramTypes
* the parameter types.
*/
public void addInvokestatic(CtClreplaced clazz, String name, CtClreplaced returnType, CtClreplaced[] paramTypes) {
String desc = Descriptor.ofMethod(returnType, paramTypes);
addInvokestatic(clazz, name, desc);
}
/**
* Appends INVOKESTATIC.
*
* @param clazz
* the target clreplaced.
* @param name
* the method name
* @param desc
* the descriptor of the method signature.
*
* @see Descriptor#ofMethod(CtClreplaced,CtClreplaced[])
*/
public void addInvokestatic(CtClreplaced clazz, String name, String desc) {
boolean isInterface;
if (clazz == THIS) {
isInterface = false;
} else {
isInterface = clazz.isInterface();
}
addInvokestatic(constPool.addClreplacedInfo(clazz), name, desc, isInterface);
}
/**
* Appends INVOKESTATIC.
*
* @param clreplacedname
* the fully-qualified clreplaced name.
* It must not be an interface-type name.
* @param name
* the method name
* @param desc
* the descriptor of the method signature.
*
* @see Descriptor#ofMethod(CtClreplaced,CtClreplaced[])
*/
public void addInvokestatic(String clreplacedname, String name, String desc) {
addInvokestatic(constPool.addClreplacedInfo(clreplacedname), name, desc);
}
/**
* Appends INVOKESTATIC.
*
* @param clazz
* the index of <code>CONSTANT_Clreplaced_info</code>
* structure. It must not be an interface type.
* @param name
* the method name
* @param desc
* the descriptor of the method signature.
*
* @see Descriptor#ofMethod(CtClreplaced,CtClreplaced[])
*/
public void addInvokestatic(int clazz, String name, String desc) {
addInvokestatic(clazz, name, desc, false);
}
private void addInvokestatic(int clazz, String name, String desc, boolean isInterface) {
add(INVOKESTATIC);
int index;
if (isInterface) {
index = constPool.addInterfaceMethodrefInfo(clazz, name, desc);
} else {
index = constPool.addMethodrefInfo(clazz, name, desc);
}
addIndex(index);
growStack(Descriptor.dataSize(desc));
}
/**
* Appends INVOKEVIRTUAL.
*
* <p>
* The specified method must not be an inherited method.
* It must be directly declared in the clreplaced specified
* in <code>clazz</code>.
*
* @param clazz
* the target clreplaced.
* @param name
* the method name
* @param returnType
* the return type.
* @param paramTypes
* the parameter types.
*/
public void addInvokevirtual(CtClreplaced clazz, String name, CtClreplaced returnType, CtClreplaced[] paramTypes) {
String desc = Descriptor.ofMethod(returnType, paramTypes);
addInvokevirtual(clazz, name, desc);
}
/**
* Appends INVOKEVIRTUAL.
*
* <p>
* The specified method must not be an inherited method.
* It must be directly declared in the clreplaced specified
* in <code>clazz</code>.
*
* @param clazz
* the target clreplaced.
* @param name
* the method name
* @param desc
* the descriptor of the method signature.
*
* @see Descriptor#ofMethod(CtClreplaced,CtClreplaced[])
*/
public void addInvokevirtual(CtClreplaced clazz, String name, String desc) {
addInvokevirtual(constPool.addClreplacedInfo(clazz), name, desc);
}
/**
* Appends INVOKEVIRTUAL.
*
* <p>
* The specified method must not be an inherited method.
* It must be directly declared in the clreplaced specified
* in <code>clreplacedname</code>.
*
* @param clreplacedname
* the fully-qualified clreplaced name.
* @param name
* the method name
* @param desc
* the descriptor of the method signature.
*
* @see Descriptor#ofMethod(CtClreplaced,CtClreplaced[])
*/
public void addInvokevirtual(String clreplacedname, String name, String desc) {
addInvokevirtual(constPool.addClreplacedInfo(clreplacedname), name, desc);
}
/**
* Appends INVOKEVIRTUAL.
*
* <p>
* The specified method must not be an inherited method.
* It must be directly declared in the clreplaced specified
* by <code>clazz</code>.
*
* @param clazz
* the index of <code>CONSTANT_Clreplaced_info</code>
* structure.
* @param name
* the method name
* @param desc
* the descriptor of the method signature.
*
* @see Descriptor#ofMethod(CtClreplaced,CtClreplaced[])
*/
public void addInvokevirtual(int clazz, String name, String desc) {
add(INVOKEVIRTUAL);
addIndex(constPool.addMethodrefInfo(clazz, name, desc));
growStack(Descriptor.dataSize(desc) - 1);
}
/**
* Appends INVOKEINTERFACE.
*
* @param clazz
* the target clreplaced.
* @param name
* the method name
* @param returnType
* the return type.
* @param paramTypes
* the parameter types.
* @param count
* the count operand of the instruction.
*/
public void addInvokeinterface(CtClreplaced clazz, String name, CtClreplaced returnType, CtClreplaced[] paramTypes, int count) {
String desc = Descriptor.ofMethod(returnType, paramTypes);
addInvokeinterface(clazz, name, desc, count);
}
/**
* Appends INVOKEINTERFACE.
*
* @param clazz
* the target clreplaced.
* @param name
* the method name
* @param desc
* the descriptor of the method signature.
* @param count
* the count operand of the instruction.
*
* @see Descriptor#ofMethod(CtClreplaced,CtClreplaced[])
*/
public void addInvokeinterface(CtClreplaced clazz, String name, String desc, int count) {
addInvokeinterface(constPool.addClreplacedInfo(clazz), name, desc, count);
}
/**
* Appends INVOKEINTERFACE.
*
* @param clreplacedname
* the fully-qualified clreplaced name.
* @param name
* the method name
* @param desc
* the descriptor of the method signature.
* @param count
* the count operand of the instruction.
*
* @see Descriptor#ofMethod(CtClreplaced,CtClreplaced[])
*/
public void addInvokeinterface(String clreplacedname, String name, String desc, int count) {
addInvokeinterface(constPool.addClreplacedInfo(clreplacedname), name, desc, count);
}
/**
* Appends INVOKEINTERFACE.
*
* @param clazz
* the index of <code>CONSTANT_Clreplaced_info</code>
* structure.
* @param name
* the method name
* @param desc
* the descriptor of the method signature.
* @param count
* the count operand of the instruction.
*
* @see Descriptor#ofMethod(CtClreplaced,CtClreplaced[])
*/
public void addInvokeinterface(int clazz, String name, String desc, int count) {
add(INVOKEINTERFACE);
addIndex(constPool.addInterfaceMethodrefInfo(clazz, name, desc));
add(count);
add(0);
growStack(Descriptor.dataSize(desc) - 1);
}
/**
* Appends INVOKEDYNAMIC.
*
* @param bootstrap
* an index into the <code>bootstrap_methods</code> array
* of the bootstrap method table.
* @param name
* the method name.
* @param desc
* the method descriptor.
* @see Descriptor#ofMethod(CtClreplaced,CtClreplaced[])
* @since 3.17
*/
public void addInvokedynamic(int bootstrap, String name, String desc) {
int nt = constPool.addNameAndTypeInfo(name, desc);
int dyn = constPool.addInvokeDynamicInfo(bootstrap, nt);
add(INVOKEDYNAMIC);
addIndex(dyn);
add(0, 0);
// replacedume ConstPool#REF_invokeStatic
growStack(Descriptor.dataSize(desc));
}
/**
* Appends LDC or LDC_W. The pushed item is a <code>String</code>
* object.
*
* @param s
* the character string pushed by LDC or LDC_W.
*/
public void addLdc(String s) {
addLdc(constPool.addStringInfo(s));
}
/**
* Appends LDC or LDC_W.
*
* @param i
* index into the constant pool.
*/
public void addLdc(int i) {
if (i > 0xFF) {
addOpcode(LDC_W);
addIndex(i);
} else {
addOpcode(LDC);
add(i);
}
}
/**
* Appends LDC2_W. The pushed item is a long value.
*/
public void addLdc2w(long l) {
addOpcode(LDC2_W);
addIndex(constPool.addLongInfo(l));
}
/**
* Appends LDC2_W. The pushed item is a double value.
*/
public void addLdc2w(double d) {
addOpcode(LDC2_W);
addIndex(constPool.addDoubleInfo(d));
}
/**
* Appends NEW.
*
* @param clazz
* the clreplaced of the created instance.
*/
public void addNew(CtClreplaced clazz) {
addOpcode(NEW);
addIndex(constPool.addClreplacedInfo(clazz));
}
/**
* Appends NEW.
*
* @param clreplacedname
* the fully-qualified clreplaced name.
*/
public void addNew(String clreplacedname) {
addOpcode(NEW);
addIndex(constPool.addClreplacedInfo(clreplacedname));
}
/**
* Appends ANEWARRAY.
*
* @param clreplacedname
* the qualified clreplaced name of the element type.
*/
public void addAnewarray(String clreplacedname) {
addOpcode(ANEWARRAY);
addIndex(constPool.addClreplacedInfo(clreplacedname));
}
/**
* Appends ICONST and ANEWARRAY.
*
* @param clazz
* the elememnt type.
* @param length
* the array length.
*/
public void addAnewarray(CtClreplaced clazz, int length) {
addIconst(length);
addOpcode(ANEWARRAY);
addIndex(constPool.addClreplacedInfo(clazz));
}
/**
* Appends NEWARRAY for primitive types.
*
* @param atype
* <code>T_BOOLEAN</code>, <code>T_CHAR</code>, ...
* @see Opcode
*/
public void addNewarray(int atype, int length) {
addIconst(length);
addOpcode(NEWARRAY);
add(atype);
}
/**
* Appends MULTINEWARRAY.
*
* @param clazz
* the array type.
* @param dimensions
* the sizes of all dimensions.
* @return the length of <code>dimensions</code>.
*/
public int addMultiNewarray(CtClreplaced clazz, int[] dimensions) {
int len = dimensions.length;
for (int i = 0; i < len; ++i) {
addIconst(dimensions[i]);
}
growStack(len);
return addMultiNewarray(clazz, len);
}
/**
* Appends MULTINEWARRAY. The size of every dimension must have been
* already pushed on the stack.
*
* @param clazz
* the array type.
* @param dim
* the number of the dimensions.
* @return the value of <code>dim</code>.
*/
public int addMultiNewarray(CtClreplaced clazz, int dim) {
add(MULTIANEWARRAY);
addIndex(constPool.addClreplacedInfo(clazz));
add(dim);
growStack(1 - dim);
return dim;
}
/**
* Appends MULTINEWARRAY.
*
* @param desc
* the type descriptor of the created array.
* @param dim
* dimensions.
* @return the value of <code>dim</code>.
*/
public int addMultiNewarray(String desc, int dim) {
add(MULTIANEWARRAY);
addIndex(constPool.addClreplacedInfo(desc));
add(dim);
growStack(1 - dim);
return dim;
}
/**
* Appends PUTFIELD.
*
* @param c
* the target clreplaced.
* @param name
* the field name.
* @param desc
* the descriptor of the field type.
*/
public void addPutfield(CtClreplaced c, String name, String desc) {
addPutfield0(c, null, name, desc);
}
/**
* Appends PUTFIELD.
*
* @param clreplacedname
* the fully-qualified name of the target clreplaced.
* @param name
* the field name.
* @param desc
* the descriptor of the field type.
*/
public void addPutfield(String clreplacedname, String name, String desc) {
// if clreplacednaem is null, the target clreplaced is THIS.
addPutfield0(null, clreplacedname, name, desc);
}
private void addPutfield0(CtClreplaced target, String clreplacedname, String name, String desc) {
add(PUTFIELD);
// target is null if it represents THIS.
int ci = clreplacedname == null ? constPool.addClreplacedInfo(target) : constPool.addClreplacedInfo(clreplacedname);
addIndex(constPool.addFieldrefInfo(ci, name, desc));
growStack(-1 - Descriptor.dataSize(desc));
}
/**
* Appends PUTSTATIC.
*
* @param c
* the target clreplaced.
* @param name
* the field name.
* @param desc
* the descriptor of the field type.
*/
public void addPutstatic(CtClreplaced c, String name, String desc) {
addPutstatic0(c, null, name, desc);
}
/**
* Appends PUTSTATIC.
*
* @param clreplacedname
* the fully-qualified name of the target clreplaced.
* @param fieldName
* the field name.
* @param desc
* the descriptor of the field type.
*/
public void addPutstatic(String clreplacedname, String fieldName, String desc) {
// if clreplacedname is null, the target clreplaced is THIS.
addPutstatic0(null, clreplacedname, fieldName, desc);
}
private void addPutstatic0(CtClreplaced target, String clreplacedname, String fieldName, String desc) {
add(PUTSTATIC);
// target is null if it represents THIS.
int ci = clreplacedname == null ? constPool.addClreplacedInfo(target) : constPool.addClreplacedInfo(clreplacedname);
addIndex(constPool.addFieldrefInfo(ci, fieldName, desc));
growStack(-Descriptor.dataSize(desc));
}
/**
* Appends ARETURN, IRETURN, .., or RETURN.
*
* @param type
* the return type.
*/
public void addReturn(CtClreplaced type) {
if (type == null) {
addOpcode(RETURN);
} else if (type.isPrimitive()) {
CtPrimitiveType ptype = (CtPrimitiveType) type;
addOpcode(ptype.getReturnOp());
} else {
addOpcode(ARETURN);
}
}
/**
* Appends RET.
*
* @param var
* local variable
*/
public void addRet(int var) {
if (var < 0x100) {
addOpcode(RET);
add(var);
} else {
addOpcode(WIDE);
addOpcode(RET);
addIndex(var);
}
}
/**
* Appends instructions for executing
* <code>java.lang.System.println(<i>message</i>)</code>.
*
* @param message
* printed message.
*/
public void addPrintln(String message) {
addGetstatic("java.lang.System", "err", "Ljava/io/PrintStream;");
addLdc(message);
addInvokevirtual("java.io.PrintStream", "println", "(Ljava/lang/String;)V");
}
}
19
Source : Bytecode.java
with Apache License 2.0
from ifeilong
with Apache License 2.0
from ifeilong
private void addPutfield0(CtClreplaced target, String clreplacedname, String name, String desc) {
add(PUTFIELD);
// target is null if it represents THIS.
int ci = clreplacedname == null ? constPool.addClreplacedInfo(target) : constPool.addClreplacedInfo(clreplacedname);
addIndex(constPool.addFieldrefInfo(ci, name, desc));
growStack(-1 - Descriptor.dataSize(desc));
}
19
Source : Bytecode.java
with Apache License 2.0
from ifeilong
with Apache License 2.0
from ifeilong
/**
* Appends CHECKCAST.
*
* @param c
* the type.
*/
public void addCheckcast(CtClreplaced c) {
addOpcode(CHECKCAST);
addIndex(constPool.addClreplacedInfo(c));
}
19
Source : Bytecode.java
with Apache License 2.0
from ifeilong
with Apache License 2.0
from ifeilong
/**
* Appends INVOKEINTERFACE.
*
* @param clazz
* the target clreplaced.
* @param name
* the method name
* @param desc
* the descriptor of the method signature.
* @param count
* the count operand of the instruction.
*
* @see Descriptor#ofMethod(CtClreplaced,CtClreplaced[])
*/
public void addInvokeinterface(CtClreplaced clazz, String name, String desc, int count) {
addInvokeinterface(constPool.addClreplacedInfo(clazz), name, desc, count);
}
19
Source : Bytecode.java
with Apache License 2.0
from ifeilong
with Apache License 2.0
from ifeilong
/**
* Appends INVOKEVIRTUAL.
*
* <p>
* The specified method must not be an inherited method.
* It must be directly declared in the clreplaced specified
* in <code>clazz</code>.
*
* @param clazz
* the target clreplaced.
* @param name
* the method name
* @param desc
* the descriptor of the method signature.
*
* @see Descriptor#ofMethod(CtClreplaced,CtClreplaced[])
*/
public void addInvokevirtual(CtClreplaced clazz, String name, String desc) {
addInvokevirtual(constPool.addClreplacedInfo(clazz), name, desc);
}
19
Source : Bytecode.java
with Apache License 2.0
from ifeilong
with Apache License 2.0
from ifeilong
/**
* Appends instructions for loading all the parameters onto the
* operand stack.
*
* @param offset
* the index of the first parameter. It is 0
* if the method is static. Otherwise, it is 1.
*/
public int addLoadParameters(CtClreplaced[] params, int offset) {
int stacksize = 0;
if (params != null) {
int n = params.length;
for (int i = 0; i < n; ++i) {
stacksize += addLoad(stacksize + offset, params[i]);
}
}
return stacksize;
}
19
Source : Bytecode.java
with Apache License 2.0
from ifeilong
with Apache License 2.0
from ifeilong
/**
* Appends PUTSTATIC.
*
* @param c
* the target clreplaced.
* @param name
* the field name.
* @param desc
* the descriptor of the field type.
*/
public void addPutstatic(CtClreplaced c, String name, String desc) {
addPutstatic0(c, null, name, desc);
}
19
Source : Bytecode.java
with Apache License 2.0
from ifeilong
with Apache License 2.0
from ifeilong
/**
* Appends INVOKESTATIC.
*
* @param clazz
* the target clreplaced.
* @param name
* the method name
* @param returnType
* the return type.
* @param paramTypes
* the parameter types.
*/
public void addInvokestatic(CtClreplaced clazz, String name, CtClreplaced returnType, CtClreplaced[] paramTypes) {
String desc = Descriptor.ofMethod(returnType, paramTypes);
addInvokestatic(clazz, name, desc);
}
See More Examples