📄 asmclassgenerator.java
字号:
/*$Id: AsmClassGenerator.java,v 1.91 2006/06/23 15:26:04 blackdrag Exp $Copyright 2003 (C) James Strachan and Bob Mcwhirter. All Rights Reserved.Redistribution and use of this software and associated documentation("Software"), with or without modification, are permitted providedthat the following conditions are met:1. Redistributions of source code must retain copyright statements and notices. Redistributions must also contain a copy of this document.2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.3. The name "groovy" must not be used to endorse or promote products derived from this Software without prior written permission of The Codehaus. For written permission, please contact info@codehaus.org.4. Products derived from this Software may not be called "groovy" nor may "groovy" appear in their names without prior written permission of The Codehaus. "groovy" is a registered trademark of The Codehaus.5. Due credit should be given to The Codehaus - http://groovy.codehaus.org/THIS SOFTWARE IS PROVIDED BY THE CODEHAUS AND CONTRIBUTORS``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUTNOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY ANDFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALLTHE CODEHAUS OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ORSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISEDOF THE POSSIBILITY OF SUCH DAMAGE.*/package org.codehaus.groovy.classgen;import groovy.lang.GroovyRuntimeException;import java.util.ArrayList;import java.util.HashSet;import java.util.Iterator;import java.util.List;import java.util.Map;import java.util.Set;import java.util.logging.Logger;import org.codehaus.groovy.ast.ASTNode;import org.codehaus.groovy.ast.AnnotatedNode;import org.codehaus.groovy.ast.AnnotationNode;import org.codehaus.groovy.ast.ClassHelper;import org.codehaus.groovy.ast.ClassNode;import org.codehaus.groovy.ast.CompileUnit;import org.codehaus.groovy.ast.ConstructorNode;import org.codehaus.groovy.ast.FieldNode;import org.codehaus.groovy.ast.InnerClassNode;import org.codehaus.groovy.ast.MethodNode;import org.codehaus.groovy.ast.Parameter;import org.codehaus.groovy.ast.PropertyNode;import org.codehaus.groovy.ast.VariableScope;import org.codehaus.groovy.ast.expr.ArgumentListExpression;import org.codehaus.groovy.ast.expr.ArrayExpression;import org.codehaus.groovy.ast.expr.AttributeExpression;import org.codehaus.groovy.ast.expr.BinaryExpression;import org.codehaus.groovy.ast.expr.BitwiseNegExpression;import org.codehaus.groovy.ast.expr.BooleanExpression;import org.codehaus.groovy.ast.expr.CastExpression;import org.codehaus.groovy.ast.expr.ClassExpression;import org.codehaus.groovy.ast.expr.ClosureExpression;import org.codehaus.groovy.ast.expr.ConstantExpression;import org.codehaus.groovy.ast.expr.ConstructorCallExpression;import org.codehaus.groovy.ast.expr.DeclarationExpression;import org.codehaus.groovy.ast.expr.Expression;import org.codehaus.groovy.ast.expr.ExpressionTransformer;import org.codehaus.groovy.ast.expr.FieldExpression;import org.codehaus.groovy.ast.expr.GStringExpression;import org.codehaus.groovy.ast.expr.ListExpression;import org.codehaus.groovy.ast.expr.MapEntryExpression;import org.codehaus.groovy.ast.expr.MapExpression;import org.codehaus.groovy.ast.expr.MethodCallExpression;import org.codehaus.groovy.ast.expr.MethodPointerExpression;import org.codehaus.groovy.ast.expr.NegationExpression;import org.codehaus.groovy.ast.expr.NotExpression;import org.codehaus.groovy.ast.expr.PostfixExpression;import org.codehaus.groovy.ast.expr.PrefixExpression;import org.codehaus.groovy.ast.expr.PropertyExpression;import org.codehaus.groovy.ast.expr.RangeExpression;import org.codehaus.groovy.ast.expr.RegexExpression;import org.codehaus.groovy.ast.expr.SpreadExpression;import org.codehaus.groovy.ast.expr.SpreadMapExpression;import org.codehaus.groovy.ast.expr.StaticMethodCallExpression;import org.codehaus.groovy.ast.expr.TernaryExpression;import org.codehaus.groovy.ast.expr.TupleExpression;import org.codehaus.groovy.ast.expr.VariableExpression;import org.codehaus.groovy.ast.stmt.AssertStatement;import org.codehaus.groovy.ast.stmt.BlockStatement;import org.codehaus.groovy.ast.stmt.BreakStatement;import org.codehaus.groovy.ast.stmt.CaseStatement;import org.codehaus.groovy.ast.stmt.CatchStatement;import org.codehaus.groovy.ast.stmt.ContinueStatement;import org.codehaus.groovy.ast.stmt.DoWhileStatement;import org.codehaus.groovy.ast.stmt.ExpressionStatement;import org.codehaus.groovy.ast.stmt.ForStatement;import org.codehaus.groovy.ast.stmt.IfStatement;import org.codehaus.groovy.ast.stmt.ReturnStatement;import org.codehaus.groovy.ast.stmt.Statement;import org.codehaus.groovy.ast.stmt.SwitchStatement;import org.codehaus.groovy.ast.stmt.SynchronizedStatement;import org.codehaus.groovy.ast.stmt.ThrowStatement;import org.codehaus.groovy.ast.stmt.TryCatchStatement;import org.codehaus.groovy.ast.stmt.WhileStatement;import org.codehaus.groovy.control.SourceUnit;import org.codehaus.groovy.runtime.ScriptBytecodeAdapter;import org.codehaus.groovy.syntax.RuntimeParserException;import org.codehaus.groovy.syntax.Types;import org.objectweb.asm.AnnotationVisitor;import org.objectweb.asm.ClassVisitor;import org.objectweb.asm.ClassWriter;import org.objectweb.asm.Label;import org.objectweb.asm.MethodVisitor;/** * Generates Java class versions of Groovy classes using ASM. * * @author <a href="mailto:james@coredevelopers.net">James Strachan</a> * @author <a href="mailto:b55r@sina.com">Bing Ran</a> * @author Jochen Theodorou * * @version $Revision: 1.91 $ */public class AsmClassGenerator extends ClassGenerator { private Logger log = Logger.getLogger(getClass().getName()); private ClassVisitor cw; private MethodVisitor cv; private GeneratorContext context; private String sourceFile; // current class details private ClassNode classNode; private ClassNode outermostClass; private String internalClassName; private String internalBaseClassName; /** maps the variable names to the JVM indices */ private CompileStack compileStack; /** have we output a return statement yet */ private boolean outputReturn; /** are we on the left or right of an expression */ private boolean leftHandExpression; // cached values MethodCaller invokeMethodMethod = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "invokeMethod"); MethodCaller invokeMethodSafeMethod = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "invokeMethodSafe"); MethodCaller invokeMethodSpreadSafeMethod = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "invokeMethodSpreadSafe"); MethodCaller invokeStaticMethodMethod = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "invokeStaticMethod"); MethodCaller invokeConstructorMethod = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "invokeConstructor"); MethodCaller invokeConstructorOfMethod = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "invokeConstructorOf"); MethodCaller invokeNoArgumentsConstructorOf = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "invokeNoArgumentsConstructorOf"); MethodCaller invokeConstructorAtMethod = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "invokeConstructorAt"); MethodCaller invokeNoArgumentsConstructorAt = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "invokeNoArgumentsConstructorAt"); MethodCaller invokeClosureMethod = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "invokeClosure"); MethodCaller invokeSuperMethodMethod = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "invokeSuperMethod"); MethodCaller invokeNoArgumentsMethod = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "invokeNoArgumentsMethod"); MethodCaller invokeNoArgumentsSafeMethod = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "invokeNoArgumentsSafeMethod"); MethodCaller invokeNoArgumentsSpreadSafeMethod = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "invokeNoArgumentsSpreadSafeMethod"); MethodCaller invokeStaticNoArgumentsMethod = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "invokeStaticNoArgumentsMethod"); MethodCaller asIntMethod = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "asInt"); MethodCaller asTypeMethod = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "asType"); MethodCaller getAttributeMethod = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "getAttribute"); MethodCaller getAttributeSafeMethod = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "getAttributeSafe"); MethodCaller getAttributeSpreadSafeMethod = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "getAttributeSpreadSafe"); MethodCaller setAttributeMethod2 = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "setAttribute2"); MethodCaller setAttributeSafeMethod2 = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "setAttributeSafe2"); MethodCaller getPropertyMethod = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "getProperty"); MethodCaller getPropertySafeMethod = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "getPropertySafe"); MethodCaller getPropertySpreadSafeMethod = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "getPropertySpreadSafe"); MethodCaller setPropertyMethod = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "setProperty"); MethodCaller setPropertyMethod2 = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "setProperty2"); MethodCaller setPropertySafeMethod2 = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "setPropertySafe2"); MethodCaller getGroovyObjectPropertyMethod = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "getGroovyObjectProperty"); MethodCaller setGroovyObjectPropertyMethod = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "setGroovyObjectProperty"); MethodCaller asIteratorMethod = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "asIterator"); MethodCaller asBool = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "asBool"); MethodCaller notBoolean = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "notBoolean"); MethodCaller notObject = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "notObject"); MethodCaller regexPattern = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "regexPattern"); MethodCaller spreadList = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "spreadList"); MethodCaller spreadMap = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "spreadMap"); MethodCaller getMethodPointer = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "getMethodPointer"); MethodCaller negation = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "negate"); MethodCaller bitNegation = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "bitNegate"); MethodCaller convertPrimitiveArray = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "convertPrimitiveArray"); MethodCaller convertToPrimitiveArray = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "convertToPrimitiveArray"); MethodCaller compareIdenticalMethod = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "compareIdentical"); MethodCaller compareEqualMethod = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "compareEqual"); MethodCaller compareNotEqualMethod = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "compareNotEqual"); MethodCaller compareToMethod = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "compareTo"); MethodCaller findRegexMethod = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "findRegex"); MethodCaller matchRegexMethod = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "matchRegex"); MethodCaller compareLessThanMethod = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "compareLessThan"); MethodCaller compareLessThanEqualMethod = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "compareLessThanEqual"); MethodCaller compareGreaterThanMethod = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "compareGreaterThan"); MethodCaller compareGreaterThanEqualMethod = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "compareGreaterThanEqual"); MethodCaller isCaseMethod = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "isCase"); MethodCaller createListMethod = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "createList"); MethodCaller createTupleMethod = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "createTuple"); MethodCaller createMapMethod = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "createMap"); MethodCaller createRangeMethod = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "createRange"); MethodCaller assertFailedMethod = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "assertFailed"); MethodCaller iteratorNextMethod = MethodCaller.newInterface(Iterator.class, "next"); MethodCaller iteratorHasNextMethod = MethodCaller.newInterface(Iterator.class, "hasNext"); // exception blocks list private List exceptionBlocks = new ArrayList(); private Set syntheticStaticFields = new HashSet(); private boolean passingClosureParams; private ConstructorNode constructorNode; private MethodNode methodNode; private BytecodeHelper helper = new BytecodeHelper(null); public static final boolean CREATE_DEBUG_INFO = true; public static final boolean CREATE_LINE_NUMBER_INFO = true; private static final boolean MARK_START = true; /*public static final String EB_SWITCH_NAME = "static.dispatching"; public boolean ENABLE_EARLY_BINDING; { // String ebSwitch = (String) AccessController.doPrivileged(new PrivilegedAction() { public Object run() { return System.getProperty(EB_SWITCH_NAME, "false"); // set default to true if early binding is on by default. } }); //System.out.println("ebSwitch = " + ebSwitch); if (ebSwitch.equals("true")) { ENABLE_EARLY_BINDING = true; } else if (ebSwitch.equals("false")) { ENABLE_EARLY_BINDING = false; } else { ENABLE_EARLY_BINDING = false; log.warning("The value of system property " + EB_SWITCH_NAME + " is not recognized. Late dispatching is assumed. "); } }*/ public static final boolean ASM_DEBUG = false; // add marker in the bytecode to show source-byecode relationship private int lineNumber = -1; private int columnNumber = -1; private ASTNode currentASTNode = null; private DummyClassGenerator dummyGen = null; private ClassWriter dummyClassWriter = null; public AsmClassGenerator( GeneratorContext context, ClassVisitor classVisitor, ClassLoader classLoader, String sourceFile ) { super(classLoader); this.context = context; this.cw = classVisitor; this.sourceFile = sourceFile; this.dummyClassWriter = new ClassWriter(true); dummyGen = new DummyClassGenerator(context, dummyClassWriter, classLoader, sourceFile); compileStack = new CompileStack(); } protected SourceUnit getSourceUnit() { return null; } // GroovyClassVisitor interface //------------------------------------------------------------------------- public void visitClass(ClassNode classNode) { // todo to be tested // createDummyClass(classNode); try { syntheticStaticFields.clear(); this.classNode = classNode; this.outermostClass = null; this.internalClassName = BytecodeHelper.getClassInternalName(classNode); this.internalBaseClassName = BytecodeHelper.getClassInternalName(classNode.getSuperClass()); cw.visit( asmJDKVersion, classNode.getModifiers(), internalClassName, null, internalBaseClassName, BytecodeHelper.getClassInternalNames(classNode.getInterfaces())
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -