📄 membercodegen.java
字号:
/* * Javassist, a Java-bytecode translator toolkit. * Copyright (C) 1999-2006 Shigeru Chiba. All Rights Reserved. * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. Alternatively, the contents of this file may be used under * the terms of the GNU Lesser General Public License Version 2.1 or later. * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. */package javassist.compiler;import javassist.*;import javassist.bytecode.*;import javassist.compiler.ast.*;import java.util.ArrayList;/* Code generator methods depending on javassist.* classes. */public class MemberCodeGen extends CodeGen { protected MemberResolver resolver; protected CtClass thisClass; protected MethodInfo thisMethod; protected boolean resultStatic; public MemberCodeGen(Bytecode b, CtClass cc, ClassPool cp) { super(b); resolver = new MemberResolver(cp); thisClass = cc; thisMethod = null; } /** * Records the currently compiled method. */ public void setThisMethod(CtMethod m) { thisMethod = m.getMethodInfo2(); if (typeChecker != null) typeChecker.setThisMethod(thisMethod); } public CtClass getThisClass() { return thisClass; } /** * Returns the JVM-internal representation of this class name. */ protected String getThisName() { return MemberResolver.javaToJvmName(thisClass.getName()); } /** * Returns the JVM-internal representation of this super class name. */ protected String getSuperName() throws CompileError { return MemberResolver.javaToJvmName( MemberResolver.getSuperclass(thisClass).getName()); } protected void insertDefaultSuperCall() throws CompileError { bytecode.addAload(0); bytecode.addInvokespecial(MemberResolver.getSuperclass(thisClass), "<init>", "()V"); } static class JsrHook extends ReturnHook { ArrayList jsrList; int var; JsrHook(CodeGen gen) { super(gen); jsrList = new ArrayList(); var = gen.getMaxLocals(); gen.incMaxLocals(1); } private void jsrJmp(Bytecode b) { b.addOpcode(JSR); jsrList.add(new Integer(b.currentPc())); b.addIndex(0); } protected void doit(Bytecode b, int opcode) { switch (opcode) { case Opcode.RETURN : jsrJmp(b); break; case ARETURN : b.addAstore(var); jsrJmp(b); b.addAload(var); break; case IRETURN : b.addIstore(var); jsrJmp(b); b.addIload(var); break; case LRETURN : b.addLstore(var); jsrJmp(b); b.addLload(var); break; case DRETURN : b.addDstore(var); jsrJmp(b); b.addDload(var); break; case FRETURN : b.addFstore(var); jsrJmp(b); b.addFload(var); break; default : throw new RuntimeException("fatal"); } } } 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(); ArrayList 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(new Integer(bc.currentPc())); bc.addIndex(0); // correct later } 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); CtClass type = resolver.lookupClassByJvmName(decl.getClassName()); decl.setClassName(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(new Integer(bc.currentPc())); bc.addIndex(0); // correct later tryNotReturn = true; } } int pcFinally = -1; 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); bc.addOpcode(JSR); int pcJsrIndex = bc.currentPc(); bc.addIndex(0); // correct later bc.addAload(var); bc.addOpcode(ATHROW); // finally clause pcFinally = bc.currentPc(); bc.write16bit(pcJsrIndex, pcFinally - pcJsrIndex + 1); int retAddr = getMaxLocals(); incMaxLocals(1); bc.growStack(1); // return address bc.addAstore(retAddr); hasReturned = false; finallyBlock.accept(this); if (!hasReturned) { bc.addOpcode(RET); bc.add(retAddr); } } int pcEnd = bc.currentPc(); patchGoto(gotoList, pcEnd); if (finallyBlock != null) { patchGoto(jsrHook.jsrList, pcFinally); if (tryNotReturn) { bc.addOpcode(JSR); bc.addIndex(pcFinally - pcEnd); } } hasReturned = !tryNotReturn; } public void atNewExpr(NewExpr expr) throws CompileError { if (expr.isArray()) atNewArrayExpr(expr); else { CtClass clazz = resolver.lookupClassByName(expr.getClassName()); String cname = clazz.getName(); ASTList args = expr.getArguments(); bytecode.addNew(cname); bytecode.addOpcode(DUP); atMethodCallCore(clazz, MethodInfo.nameInit, args, false, true, -1, null); exprType = CLASS; arrayDim = 0; className = MemberResolver.javaToJvmName(cname); } } public void atNewArrayExpr(NewExpr expr) throws CompileError { int type = expr.getArrayType(); ASTList size = expr.getArraySize(); ASTList classname = expr.getClassName(); 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, classname, size); return; } ASTree sizeExpr = size.head(); atNewArrayExpr2(type, sizeExpr, Declarator.astToClassName(classname, '/'), init); } private void atNewArrayExpr2(int type, ASTree sizeExpr, String jvmClassname, 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 elementClass; if (type == CLASS) { elementClass = resolveClassName(jvmClassname); bytecode.addAnewarray(MemberResolver.jvmToJavaName(elementClass)); } else { elementClass = 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; className = elementClass; } private static void badNewExpr() throws CompileError { throw new CompileError("bad new expression"); } protected void atArrayVariableAssign(ArrayInit init, int varType, int varArray, String varClass) throws CompileError { atNewArrayExpr2(varType, null, varClass, init); } public void atArrayInit(ArrayInit init) throws CompileError { throw new CompileError("array initializer is not supported"); } protected void atMultiNewArray(int type, ASTList classname, ASTList size) throws CompileError { int count, dim; dim = size.length(); for (count = 0; size != null; size = size.tail()) { ASTree s = size.head();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -