📄 asmclassgenerator.java
字号:
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); // todo need to add blockscope handling CatchStatement catchStatement = statement.getCatchStatement(0); Statement tryStatement = statement.getTryStatement(); if (tryStatement.isEmpty() || catchStatement == null) { final Label l0 = new Label(); cv.visitLabel(l0); tryStatement.visit(this); int index1 = compileStack.defineTemporaryVariable("exception",false); int index2 = compileStack.defineTemporaryVariable("exception",false); final Label l1 = new Label(); cv.visitJumpInsn(JSR, l1); final Label l2 = new Label(); cv.visitLabel(l2); final Label l3 = new Label(); cv.visitJumpInsn(GOTO, l3); final Label l4 = new Label(); cv.visitLabel(l4); cv.visitVarInsn(ASTORE, index1); cv.visitJumpInsn(JSR, l1); final Label l5 = new Label(); cv.visitLabel(l5); cv.visitVarInsn(ALOAD, index1); cv.visitInsn(ATHROW); cv.visitLabel(l1); cv.visitVarInsn(ASTORE, index2); statement.getFinallyStatement().visit(this); cv.visitVarInsn(RET, index2); cv.visitLabel(l3); exceptionBlocks.add(new Runnable() { public void run() { cv.visitTryCatchBlock(l0, l2, l4, null); cv.visitTryCatchBlock(l4, l5, l4, null); } }); } else { int finallySubAddress = compileStack.defineTemporaryVariable("exception",false); int anyExceptionIndex = compileStack.defineTemporaryVariable("exception",false); // 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); // start finally cv.visitLabel(finallyStart); Label finallySub = new Label(); // run finally sub cv.visitJumpInsn(JSR, finallySub); // 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); // run finally subroutine cv.visitJumpInsn(JSR, finallySub); // load the exception and rethrow it cv.visitVarInsn(ALOAD, anyExceptionIndex); cv.visitInsn(ATHROW); // start the finally subroutine cv.visitLabel(finallySub); // store jump address cv.visitVarInsn(ASTORE, finallySubAddress); if (!statement.getFinallyStatement().isEmpty()) statement.getFinallyStatement().visit(this); // return from subroutine cv.visitVarInsn(RET, finallySubAddress); // 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); } public void visitBreakStatement(BreakStatement statement) { onLineNumber(statement, "visitBreakStatement"); visitStatement(statement); String name = statement.getLabel(); Label breakLabel; if (name!=null) { breakLabel = compileStack.getNamedBreakLabel(name); } else { breakLabel= compileStack.getBreakLabel(); } cv.visitJumpInsn(GOTO, breakLabel); } public void visitContinueStatement(ContinueStatement statement) { onLineNumber(statement, "visitContinueStatement"); visitStatement(statement); String name = statement.getLabel(); Label continueLabel = compileStack.getContinueLabel(); if (name!=null) continueLabel = compileStack.getNamedContinueLabel(name); cv.visitJumpInsn(GOTO, continueLabel); } public void visitSynchronizedStatement(SynchronizedStatement statement) { onLineNumber(statement, "visitSynchronizedStatement"); visitStatement(statement); statement.getExpression().visit(this); int index = compileStack.defineTemporaryVariable("synchronized", ClassHelper.Integer_TYPE,true); cv.visitVarInsn(ALOAD, index); cv.visitInsn(MONITORENTER); final Label l0 = new Label(); cv.visitLabel(l0); statement.getCode().visit(this); cv.visitVarInsn(ALOAD, index); cv.visitInsn(MONITOREXIT); final Label l1 = new Label(); cv.visitJumpInsn(GOTO, l1); final Label l2 = new Label(); cv.visitLabel(l2); cv.visitVarInsn(ALOAD, index); cv.visitInsn(MONITOREXIT); cv.visitInsn(ATHROW); cv.visitLabel(l1); exceptionBlocks.add(new Runnable() { public void run() { cv.visitTryCatchBlock(l0, l2, l2, null); } }); } public void visitThrowStatement(ThrowStatement statement) { onLineNumber(statement, "visitThrowStatement"); visitStatement(statement); statement.getExpression().visit(this); // we should infer the type of the exception from the expression cv.visitTypeInsn(CHECKCAST, "java/lang/Throwable"); cv.visitInsn(ATHROW); } public void visitReturnStatement(ReturnStatement statement) { onLineNumber(statement, "visitReturnStatement"); visitStatement(statement); ClassNode returnType = methodNode.getReturnType(); if (returnType==ClassHelper.VOID_TYPE) { if (!(statement == ReturnStatement.RETURN_NULL_OR_VOID)) { throwException("Cannot use return statement with an expression on a method that returns void"); } cv.visitInsn(RETURN); outputReturn = true; return; } Expression expression = statement.getExpression(); evaluateExpression(expression); if (returnType==ClassHelper.OBJECT_TYPE && expression.getType() != null && expression.getType()==ClassHelper.VOID_TYPE) { cv.visitInsn(ACONST_NULL); // cheat the caller cv.visitInsn(ARETURN); } else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -