asmclassgenerator.java
来自「Groovy动态语言 运行在JVM中的动态语言 可以方便的处理业务逻辑变化大的业」· Java 代码 · 共 1,558 行 · 第 1/5 页
JAVA
1,558 行
compileStack.pop();
}
public void visitWhileLoop(WhileStatement loop) {
onLineNumber(loop, "visitWhileLoop");
visitStatement(loop);
compileStack.pushLoop(loop.getStatementLabel());
Label continueLabel = compileStack.getContinueLabel();
Label breakLabel = compileStack.getBreakLabel();
cv.visitLabel(continueLabel);
loop.getBooleanExpression().visit(this);
cv.visitJumpInsn(IFEQ, breakLabel);
loop.getLoopBlock().visit(this);
cv.visitJumpInsn(GOTO, continueLabel);
cv.visitLabel(breakLabel);
compileStack.pop();
}
public void visitDoWhileLoop(DoWhileStatement loop) {
onLineNumber(loop, "visitDoWhileLoop");
visitStatement(loop);
compileStack.pushLoop(loop.getStatementLabel());
Label breakLabel = compileStack.getBreakLabel();
Label continueLabel = compileStack.getContinueLabel();
cv.visitLabel(continueLabel);
loop.getLoopBlock().visit(this);
loop.getBooleanExpression().visit(this);
cv.visitJumpInsn(IFEQ, continueLabel);
cv.visitLabel(breakLabel);
compileStack.pop();
}
public void visitIfElse(IfStatement ifElse) {
onLineNumber(ifElse, "visitIfElse");
visitStatement(ifElse);
ifElse.getBooleanExpression().visit(this);
Label l0 = new Label();
cv.visitJumpInsn(IFEQ, l0);
ifElse.getIfBlock().visit(this);
Label l1 = new Label();
cv.visitJumpInsn(GOTO, l1);
cv.visitLabel(l0);
ifElse.getElseBlock().visit(this);
cv.visitLabel(l1);
}
public void visitTernaryExpression(TernaryExpression expression) {
onLineNumber(expression, "visitTernaryExpression");
expression.getBooleanExpression().visit(this);
Label l0 = new Label();
cv.visitJumpInsn(IFEQ, l0);
visitAndAutoboxBoolean(expression.getTrueExpression());
Label l1 = new Label();
cv.visitJumpInsn(GOTO, l1);
cv.visitLabel(l0);
visitAndAutoboxBoolean(expression.getFalseExpression());
cv.visitLabel(l1);
}
public void visitAssertStatement(AssertStatement statement) {
onLineNumber(statement, "visitAssertStatement");
visitStatement(statement);
BooleanExpression booleanExpression = statement.getBooleanExpression();
booleanExpression.visit(this);
Label l0 = new Label();
cv.visitJumpInsn(IFEQ, l0);
// do nothing
Label l1 = new Label();
cv.visitJumpInsn(GOTO, l1);
cv.visitLabel(l0);
// push expression string onto stack
String expressionText = booleanExpression.getText();
List list = new ArrayList();
addVariableNames(booleanExpression, list);
if (list.isEmpty()) {
cv.visitLdcInsn(expressionText);
}
else {
boolean first = true;
// lets create a new expression
cv.visitTypeInsn(NEW, "java/lang/StringBuffer");
cv.visitInsn(DUP);
cv.visitLdcInsn(expressionText + ". Values: ");
cv.visitMethodInsn(INVOKESPECIAL, "java/lang/StringBuffer", "<init>", "(Ljava/lang/String;)V");
int tempIndex = compileStack.defineTemporaryVariable("assert",true);
for (Iterator iter = list.iterator(); iter.hasNext();) {
String name = (String) iter.next();
String text = name + " = ";
if (first) {
first = false;
}
else {
text = ", " + text;
}
cv.visitVarInsn(ALOAD, tempIndex);
cv.visitLdcInsn(text);
cv.visitMethodInsn(
INVOKEVIRTUAL,
"java/lang/StringBuffer",
"append",
"(Ljava/lang/Object;)Ljava/lang/StringBuffer;");
cv.visitInsn(POP);
cv.visitVarInsn(ALOAD, tempIndex);
new VariableExpression(name).visit(this);
cv.visitMethodInsn(
INVOKEVIRTUAL,
"java/lang/StringBuffer",
"append",
"(Ljava/lang/Object;)Ljava/lang/StringBuffer;");
cv.visitInsn(POP);
}
cv.visitVarInsn(ALOAD, tempIndex);
compileStack.removeVar(tempIndex);
}
// now the optional exception expression
statement.getMessageExpression().visit(this);
assertFailedMethod.call(cv);
cv.visitLabel(l1);
}
private void addVariableNames(Expression expression, List list) {
if (expression instanceof BooleanExpression) {
BooleanExpression boolExp = (BooleanExpression) expression;
addVariableNames(boolExp.getExpression(), list);
}
else if (expression instanceof BinaryExpression) {
BinaryExpression binExp = (BinaryExpression) expression;
addVariableNames(binExp.getLeftExpression(), list);
addVariableNames(binExp.getRightExpression(), list);
}
else if (expression instanceof VariableExpression) {
VariableExpression varExp = (VariableExpression) expression;
list.add(varExp.getName());
}
}
public void visitTryCatchFinally(TryCatchStatement statement) {
onLineNumber(statement, "visitTryCatchFinally");
visitStatement(statement);
CatchStatement catchStatement = statement.getCatchStatement(0);
Statement tryStatement = statement.getTryStatement();
final Statement finallyStatement = statement.getFinallyStatement();
int anyExceptionIndex = compileStack.defineTemporaryVariable("exception",false);
if (!finallyStatement.isEmpty()) {
compileStack.pushFinallyBlock(
new Runnable(){
public void run(){finallyStatement.visit(AsmClassGenerator.this);}
}
);
}
// start try block, label needed for exception table
final Label tryStart = new Label();
cv.visitLabel(tryStart);
tryStatement.visit(this);
// goto finally part
final Label finallyStart = new Label();
cv.visitJumpInsn(GOTO, finallyStart);
// marker needed for Exception table
final Label tryEnd = new Label();
cv.visitLabel(tryEnd);
for (Iterator it=statement.getCatchStatements().iterator(); it.hasNext();) {
catchStatement = (CatchStatement) it.next();
ClassNode exceptionType = catchStatement.getExceptionType();
// start catch block, label needed for exception table
final Label catchStart = new Label();
cv.visitLabel(catchStart);
// create exception variable and store the exception
compileStack.defineVariable(catchStatement.getVariable(),true);
// handle catch body
catchStatement.visit(this);
// goto finally start
cv.visitJumpInsn(GOTO, finallyStart);
// add exception to table
final String exceptionTypeInternalName = BytecodeHelper.getClassInternalName(exceptionType);
exceptionBlocks.add(new Runnable() {
public void run() {
cv.visitTryCatchBlock(tryStart, tryEnd, catchStart, exceptionTypeInternalName);
}
});
}
// marker needed for the exception table
final Label endOfAllCatches = new Label();
cv.visitLabel(endOfAllCatches);
// remove the finally, don't let it visit itself
if (!finallyStatement.isEmpty()) compileStack.popFinallyBlock();
// start finally
cv.visitLabel(finallyStart);
finallyStatement.visit(this);
// goto end of finally
Label afterFinally = new Label();
cv.visitJumpInsn(GOTO, afterFinally);
// start a block catching any Exception
final Label catchAny = new Label();
cv.visitLabel(catchAny);
//store exception
cv.visitVarInsn(ASTORE, anyExceptionIndex);
finallyStatement.visit(this);
// load the exception and rethrow it
cv.visitVarInsn(ALOAD, anyExceptionIndex);
cv.visitInsn(ATHROW);
// end of all catches and finally parts
cv.visitLabel(afterFinally);
// add catch any block to exception table
exceptionBlocks.add(new Runnable() {
public void run() {
cv.visitTryCatchBlock(tryStart, endOfAllCatches, catchAny, null);
}
});
}
public void visitSwitch(SwitchStatement statement) {
onLineNumber(statement, "visitSwitch");
visitStatement(statement);
statement.getExpression().visit(this);
// switch does not have a continue label. use its parent's for continue
Label breakLabel = compileStack.pushSwitch();
int switchVariableIndex = compileStack.defineTemporaryVariable("switch",true);
List caseStatements = statement.getCaseStatements();
int caseCount = caseStatements.size();
Label[] labels = new Label[caseCount + 1];
for (int i = 0; i < caseCount; i++) {
labels[i] = new Label();
}
int i = 0;
for (Iterator iter = caseStatements.iterator(); iter.hasNext(); i++) {
CaseStatement caseStatement = (CaseStatement) iter.next();
visitCaseStatement(caseStatement, switchVariableIndex, labels[i], labels[i + 1]);
}
statement.getDefaultStatement().visit(this);
cv.visitLabel(breakLabel);
compileStack.pop();
}
public void visitCaseStatement(CaseStatement statement) {
}
public void visitCaseStatement(
CaseStatement statement,
int switchVariableIndex,
Label thisLabel,
Label nextLabel) {
onLineNumber(statement, "visitCaseStatement");
cv.visitVarInsn(ALOAD, switchVariableIndex);
statement.getExpression().visit(this);
isCaseMethod.call(cv);
Label l0 = new Label();
cv.visitJumpInsn(IFEQ, l0);
cv.visitLabel(thisLabel);
statement.getCode().visit(this);
// now if we don't finish with a break we need to jump past
// the next comparison
if (nextLabel != null) {
cv.visitJumpInsn(GOTO, nextLabel);
}
cv.visitLabel(l0);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?