[Proxool-cvs] proxool/src/java/org/logicalcobwebs/cglib/core AbstractClassGenerator.java,NONE,1.1 Bl
UNMAINTAINED!
Brought to you by:
billhorsman
Update of /cvsroot/proxool/proxool/src/java/org/logicalcobwebs/cglib/core In directory sc8-pr-cvs1:/tmp/cvs-serv25673/src/java/org/logicalcobwebs/cglib/core Added Files: AbstractClassGenerator.java Block.java ClassEmitter.java ClassGenerator.java ClassNameReader.java ClassesKey.java CodeEmitter.java CodeGenerationException.java CollectionUtils.java Constants.java Converter.java Customizer.java DebuggingClassWriter.java DefaultGeneratorStrategy.java DefaultNamingPolicy.java DuplicatesPredicate.java EmitUtils.java GeneratorStrategy.java KeyFactory.java Local.java MethodWrapper.java NamingPolicy.java ObjectSwitchCallback.java Predicate.java ProcessArrayCallback.java ProcessSwitchCallback.java ReflectUtils.java RemappingCodeVisitor.java Signature.java TinyBitSet.java Transformer.java TypeUtils.java VisibilityPredicate.java Log Message: Repackaged Cglib project --- NEW FILE: AbstractClassGenerator.java --- /* * The Apache Software License, Version 1.1 * * Copyright (c) 2002 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 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 end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Apache" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact ap...@ap.... * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 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 ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */ package org.logicalcobwebs.cglib.core; import java.io.*; import java.lang.reflect.*; import java.util.*; import org.logicalcobwebs.asm.ClassReader; import org.logicalcobwebs.asm.ClassVisitor; import org.logicalcobwebs.asm.ClassWriter; import org.logicalcobwebs.asm.Type; /** * Abstract class for all code-generating CGLIB utilities. * In addition to caching generated classes for performance, it provides hooks for * customizing the <code>ClassLoader</code>, name of the generated class, and transformations * applied before generation. */ abstract public class AbstractClassGenerator implements ClassGenerator { private static final Object NAME_KEY = new Object(); private GeneratorStrategy strategy = DefaultGeneratorStrategy.INSTANCE; private NamingPolicy namingPolicy; private Source source; private ClassLoader classLoader; private String namePrefix; private Object key; private boolean useCache = true; protected static class Source { String name; Map cache = new WeakHashMap(); public Source(String name) { this.name = name; } } protected AbstractClassGenerator(Source source) { this.source = source; } protected void setNamePrefix(String namePrefix) { this.namePrefix = namePrefix; } final protected String getClassName() { return getClassName(getClassLoader()); } private String getClassName(ClassLoader loader) { NamingPolicy np = (namingPolicy != null) ? namingPolicy : DefaultNamingPolicy.INSTANCE; final Set nameCache = getClassNameCache(loader); return np.getClassName(namePrefix, source.name, key, new Predicate() { public boolean evaluate(Object arg) { return nameCache.contains(arg); } }); } private Set getClassNameCache(ClassLoader loader) { return (Set)((Map)source.cache.get(loader)).get(NAME_KEY); } /** * Set the <code>ClassLoader</code> in which the class will be generated. * Concrete subclasses of <code>AbstractClassGenerator</code> (such as <code>Enhancer</code>) * will try to choose an appropriate default if this is unset. * <p> * Classes are cached per-<code>ClassLoader</code> using a <code>WeakHashMap</code>, to allow * the generated classes to be removed when the associated loader is garbage collected. * @param classLoader the loader to generate the new class with, or null to use the default */ public void setClassLoader(ClassLoader classLoader) { this.classLoader = classLoader; } /** * Override the default naming policy. * @see DefaultNamingPolicy * @param namingPolicy the custom policy, or null to use the default */ public void setNamingPolicy(NamingPolicy namingPolicy) { this.namingPolicy = namingPolicy; } /** * Whether use and update the static cache of generated classes * for a class with the same properties. Default is <code>true</code>. */ public void setUseCache(boolean useCache) { this.useCache = useCache; } /** * Set the strategy to use to create the bytecode from this generator. * By default an instance of {@see DefaultGeneratorStrategy} is used. */ public void setStrategy(GeneratorStrategy strategy) { this.strategy = strategy; } // TODO: pluggable policy? protected ClassLoader getClassLoader() { ClassLoader t = classLoader; if (t == null) { t = getDefaultClassLoader(); } if (t == null) { t = getClass().getClassLoader(); } if (t == null) { throw new IllegalStateException("Cannot determine classloader"); } return t; } abstract protected ClassLoader getDefaultClassLoader(); protected Object create(Object key) { try { Object instance = null; synchronized (source) { ClassLoader loader = getClassLoader(); Map cache2 = null; if (useCache) { cache2 = (Map)source.cache.get(loader); if (cache2 != null) { instance = cache2.get(key); } else { cache2 = new HashMap(); cache2.put(NAME_KEY, new HashSet()); source.cache.put(loader, cache2); } } if (instance == null) { this.key = key; byte[] b = strategy.generate(this); String className = ClassNameReader.getClassName(new ClassReader(b)); getClassNameCache(loader).add(className); instance = firstInstance(ReflectUtils.defineClass(className, b, loader)); if (useCache) { cache2.put(key, instance); } return instance; } } return nextInstance(instance); } catch (RuntimeException e) { throw e; } catch (Error e) { throw e; } catch (Exception e) { throw new CodeGenerationException(e); } } abstract protected Object firstInstance(Class type) throws Exception; abstract protected Object nextInstance(Object instance) throws Exception; } --- NEW FILE: Block.java --- /* * The Apache Software License, Version 1.1 * * Copyright (c) 2002 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 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 end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Apache" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact ap...@ap.... * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 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 ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */ package org.logicalcobwebs.cglib.core; import org.logicalcobwebs.asm.Label; public class Block { private CodeEmitter e; private Label start; private Label end; public Block(CodeEmitter e) { this.e = e; start = e.mark(); } public CodeEmitter getCodeEmitter() { return e; } public void end() { if (end != null) { throw new IllegalStateException("end of label already set"); } end = e.mark(); } public Label getStart() { return start; } public Label getEnd() { return end; } } --- NEW FILE: ClassEmitter.java --- /* * The Apache Software License, Version 1.1 * * Copyright (c) 2002 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 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 end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Apache" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact ap...@ap.... * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 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 ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */ package org.logicalcobwebs.cglib.core; import java.io.*; import java.util.*; import org.logicalcobwebs.asm.*; /** * @author Juozas Baliuka, Chris Nokleberg */ public class ClassEmitter extends ClassAdapter { private static final Signature STATIC_HOOK = TypeUtils.parseSignature("void CGLIB$STATIC_HOOK()"); private static final String STATIC_HOOK_FLAG = "CGLIB$STATIC_HOOK_FLAG"; private int access; private Type classType; private Type superType; private Map fieldInfo; private boolean seenStatic; private CodeEmitter hook; private boolean ended; private ClassVisitor outer; public ClassEmitter(ClassVisitor cv) { super(null); setTarget(cv, this); } public ClassEmitter() { super(null); } public void setTarget(ClassVisitor cv, ClassVisitor outer) { this.cv = cv; this.outer = outer; fieldInfo = new HashMap(); seenStatic = false; hook = null; ended = false; } public void begin_class(int access, String className, Type superType, Type[] interfaces, String sourceFile) { this.access = access; this.classType = Type.getType("L" + className.replace('.', '/') + ";"); this.superType = (superType != null) ? superType : Constants.TYPE_OBJECT; cv.visit(access, this.classType.getInternalName(), this.superType.getInternalName(), TypeUtils.toInternalNames(interfaces), sourceFile); init(); } public CodeEmitter getStaticHook() { if (TypeUtils.isInterface(access)) { throw new IllegalStateException("static hook is invalid for this class"); } if (hook == null) { ClassEmitter oe = new ClassEmitter(outer); oe.declare_field(Constants.PRIVATE_FINAL_STATIC, STATIC_HOOK_FLAG, Type.BOOLEAN_TYPE, null, null); CodeEmitter e = oe.begin_method(Constants.ACC_STATIC, STATIC_HOOK, null, null); Label ok = e.make_label(); e.getstatic(classType, STATIC_HOOK_FLAG, Type.BOOLEAN_TYPE); e.if_jump(e.EQ, ok); e.return_value(); e.mark(ok); e.push(true); e.putstatic(classType, STATIC_HOOK_FLAG, Type.BOOLEAN_TYPE); } return hook; } protected void init() { } public int getAccess() { return access; } public Type getClassType() { return classType; } public Type getSuperType() { return superType; } public void end_class() { if (seenStatic && hook == null) { getStaticHook(); // force hook method creation } if (hook != null) { if (!seenStatic) { CodeVisitor v = outer.visitMethod(Constants.ACC_STATIC, Constants.SIG_STATIC.getName(), Constants.SIG_STATIC.getDescriptor(), null, null); v.visitInsn(Constants.RETURN); v.visitMaxs(0, 0); } ended = true; hook.return_value(); hook.end_method(); } cv.visitEnd(); } public CodeEmitter begin_method(int access, Signature sig, Type[] exceptions, Attribute attrs) { CodeVisitor v = cv.visitMethod(access, sig.getName(), sig.getDescriptor(), TypeUtils.toInternalNames(exceptions), attrs); if (sig.equals(STATIC_HOOK)) { hook = new CodeEmitter(this, v, access, sig, exceptions) { public boolean isStaticHook() { return true; } public void visitMaxs(int maxStack, int maxLocals) { if (ended) { super.visitMaxs(maxStack, maxLocals); } } public void visitInsn(int insn) { if (insn != Constants.RETURN || ended) { super.visitInsn(insn); } } }; return hook; } else { CodeEmitter e = new CodeEmitter(this, v, access, sig, exceptions); if (sig.equals(Constants.SIG_STATIC) && !TypeUtils.isInterface(this.access)) { seenStatic = true; e.invoke_static_this(STATIC_HOOK); } return e; } } public CodeEmitter begin_static() { return begin_method(Constants.ACC_STATIC, Constants.SIG_STATIC, null, null); } public void declare_field(int access, String name, Type type, Object value, Attribute attrs) { FieldInfo existing = (FieldInfo)fieldInfo.get(name); FieldInfo info = new FieldInfo(access, name, type, value); if (existing != null) { if (!info.equals(existing)) { throw new IllegalArgumentException("Field \"" + name + "\" has been declared differently"); } } else { fieldInfo.put(name, info); cv.visitField(access, name, type.getDescriptor(), value, attrs); } } public void define_attribute(Attribute attrs) { cv.visitAttribute(attrs); } // TODO: make public? boolean isFieldDeclared(String name) { return fieldInfo.get(name) != null; } FieldInfo getFieldInfo(String name) { FieldInfo field = (FieldInfo)fieldInfo.get(name); if (field == null) { throw new IllegalArgumentException("Field " + name + " is not declared in " + classType.getClassName()); } return field; } static class FieldInfo { int access; String name; Type type; Object value; public FieldInfo(int access, String name, Type type, Object value) { this.access = access; this.name = name; this.type = type; this.value = value; } public boolean equals(Object o) { if (o == null) return false; if (!(o instanceof FieldInfo)) return false; FieldInfo other = (FieldInfo)o; if (access != other.access || !name.equals(other.name) || !type.equals(other.type)) { return false; } if ((value == null) ^ (other.value == null)) return false; if (value != null && !value.equals(other.value)) return false; return true; } public int hashCode() { return access ^ name.hashCode() ^ type.hashCode() ^ ((value == null) ? 0 : value.hashCode()); } } public void visit(int access, String name, String superName, String[] interfaces, String sourceFile) { begin_class(access, name.replace('/', '.'), TypeUtils.fromInternalName(superName), TypeUtils.fromInternalNames(interfaces), sourceFile); } public void visitEnd() { end_class(); } public void visitField(int access, String name, String desc, Object value, Attribute attrs) { declare_field(access, name, Type.getType(desc), value, attrs); } // TODO: handle visitInnerClass? public CodeVisitor visitMethod(int access, String name, String desc, String[] exceptions, Attribute attrs) { return begin_method(access, new Signature(name, desc), TypeUtils.fromInternalNames(exceptions), attrs); } public void visitAttribute(Attribute attrs) { define_attribute(attrs); } } --- NEW FILE: ClassGenerator.java --- /* * The Apache Software License, Version 1.1 * * Copyright (c) 2002 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 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 end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Apache" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact ap...@ap.... * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 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 ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */ package org.logicalcobwebs.cglib.core; import org.logicalcobwebs.asm.ClassVisitor; public interface ClassGenerator { void generateClass(ClassVisitor v) throws Exception; } --- NEW FILE: ClassNameReader.java --- /* * The Apache Software License, Version 1.1 * * Copyright (c) 2002 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 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 end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Apache" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact ap...@ap.... * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 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 ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */ package org.logicalcobwebs.cglib.core; import org.logicalcobwebs.asm.ClassAdapter; import org.logicalcobwebs.asm.ClassReader; // TODO: optimize (ClassReader buffers entire class before accept) public class ClassNameReader { private ClassNameReader() { } private static final EarlyExitException EARLY_EXIT = new EarlyExitException(); private static class EarlyExitException extends RuntimeException { } public static String getClassName(ClassReader r) { final String[] array = new String[1]; try { r.accept(new ClassAdapter(null) { public void visit(int access, String name, String superName, String[] interfaces, String sourceFile) { array[0] = name.replace('/', '.'); throw EARLY_EXIT; } }, true); } catch (EarlyExitException e) { } return array[0]; } } --- NEW FILE: ClassesKey.java --- /* * The Apache Software License, Version 1.1 * * Copyright (c) 2002 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 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 end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Apache" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact ap...@ap.... * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 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 ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */ package org.logicalcobwebs.cglib.core; public class ClassesKey { private static final Key FACTORY = (Key)KeyFactory.create(Key.class, KeyFactory.OBJECT_BY_CLASS); interface Key { Object newInstance(Object[] array); } private ClassesKey() { } public static Object create(Object[] array) { return FACTORY.newInstance(array); } } --- NEW FILE: CodeEmitter.java --- /* * The Apache Software License, Version 1.1 * * Copyright (c) 2002 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 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 end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Apache" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact ap...@ap.... * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 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 ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */ package org.logicalcobwebs.cglib.core; import java.io.*; import java.lang.reflect.Method; import java.util.*; import org.logicalcobwebs.asm.*; /** * @author Juozas Baliuka, Chris Nokleberg */ public class CodeEmitter extends RemappingCodeVisitor { private static final Signature BOOLEAN_VALUE = TypeUtils.parseSignature("boolean booleanValue()"); private static final Signature CHAR_VALUE = TypeUtils.parseSignature("char charValue()"); private static final Signature LONG_VALUE = TypeUtils.parseSignature("long longValue()"); private static final Signature DOUBLE_VALUE = TypeUtils.parseSignature("double doubleValue()"); private static final Signature FLOAT_VALUE = TypeUtils.parseSignature("float floatValue()"); private static final Signature INT_VALUE = TypeUtils.parseSignature("int intValue()"); private static final Signature CSTRUCT_NULL = TypeUtils.parseConstructor(""); private static final Signature CSTRUCT_STRING = TypeUtils.parseConstructor("String"); public static final int ADD = Constants.IADD; public static final int MUL = Constants.IMUL; public static final int XOR = Constants.IXOR; public static final int USHR = Constants.IUSHR; public static final int SUB = Constants.ISUB; public static final int DIV = Constants.IDIV; public static final int NEG = Constants.INEG; public static final int REM = Constants.IREM; public static final int AND = Constants.IAND; public static final int OR = Constants.IOR; public static final int GT = Constants.IFGT; public static final int LT = Constants.IFLT; public static final int GE = Constants.IFGE; public static final int LE = Constants.IFLE; public static final int NE = Constants.IFNE; public static final int EQ = Constants.IFEQ; private ClassEmitter ce; private State state; private static class State { int access; Signature sig; Type[] argumentTypes; int localOffset; Type[] exceptionTypes; State(int access, Signature sig, Type[] exceptionTypes) { this.access = access; this.sig = sig; this.exceptionTypes = exceptionTypes; localOffset = TypeUtils.isStatic(access) ? 0 : 1; argumentTypes = sig.getArgumentTypes(); } } CodeEmitter(ClassEmitter ce, CodeVisitor cv, int access, Signature sig, Type[] exceptionTypes) { super(cv, access, sig.getArgumentTypes()); this.ce = ce; state = new State(access, sig, exceptionTypes); } public CodeEmitter(CodeEmitter wrap) { super(wrap); this.ce = wrap.ce; this.state = wrap.state; } public boolean isStaticHook() { return false; } public Signature getSignature() { return state.sig; } public Type getReturnType() { return state.sig.getReturnType(); } /* wait until these are needed public Type[] getArgumentTypes() { return state.argumentTypes; } public Type[] getExceptionTypes() { return state.getExceptionTypes(); } */ public ClassEmitter getClassEmitter() { return ce; } public void end_method() { visitMaxs(0, 0); } public Block begin_block() { return new Block(this); } public void catch_exception(Block block, Type exception) { if (block.getEnd() == null) { throw new IllegalStateException("end of block is unset"); } cv.visitTryCatchBlock(block.getStart(), block.getEnd(), mark(), exception.getInternalName()); } public void goTo(Label label) { cv.visitJumpInsn(Constants.GOTO, label); } public void ifnull(Label label) { cv.visitJumpInsn(Constants.IFNULL, label); } public void ifnonnull(Label label) { cv.visitJumpInsn(Constants.IFNONNULL, label); } public void if_jump(int mode, Label label) { cv.visitJumpInsn(mode, label); } public void if_icmp(int mode, Label label) { if_cmp(Type.INT_TYPE, mode, label); } public void if_cmp(Type type, int mode, Label label) { int intOp = -1; int jumpmode = mode; switch (mode) { case GE: jumpmode = LT; break; case LE: jumpmode = GT; break; } switch (type.getSort()) { case Type.LONG: cv.visitInsn(Constants.LCMP); break; case Type.DOUBLE: cv.visitInsn(Constants.DCMPG); break; case Type.FLOAT: cv.visitInsn(Constants.FCMPG); break; case Type.ARRAY: case Type.OBJECT: switch (mode) { case EQ: cv.visitJumpInsn(Constants.IF_ACMPEQ, label); return; case NE: cv.visitJumpInsn(Constants.IF_ACMPNE, label); return; } throw new IllegalArgumentException("Bad comparison for type " + type); default: switch (mode) { case EQ: intOp = Constants.IF_ICMPEQ; break; case NE: intOp = Constants.IF_ICMPNE; break; case GE: swap(); /* fall through */ case LT: intOp = Constants.IF_ICMPLT; break; case LE: swap(); /* fall through */ case GT: intOp = Constants.IF_ICMPGT; break; } cv.visitJumpInsn(intOp, label); return; } if_jump(jumpmode, label); } public void pop() { cv.visitInsn(Constants.POP); } public void pop2() { cv.visitInsn(Constants.POP2); } public void dup() { cv.visitInsn(Constants.DUP); } public void dup2() { cv.visitInsn(Constants.DUP2); } public void dup_x1() { cv.visitInsn(Constants.DUP_X1); } public void dup_x2() { cv.visitInsn(Constants.DUP_X2); } public void dup2_x1() { cv.visitInsn(Constants.DUP2_X1); } public void dup2_x2() { cv.visitInsn(Constants.DUP2_X2); } public void swap() { cv.visitInsn(Constants.SWAP); } public void aconst_null() { cv.visitInsn(Constants.ACONST_NULL); } public void swap(Type prev, Type type) { if (type.getSize() == 1) { if (prev.getSize() == 1) { swap(); // same as dup_x1(), pop(); } else { dup_x2(); pop(); } } else { if (prev.getSize() == 1) { dup2_x1(); pop2(); } else { dup2_x2(); pop2(); } } } public void monitorenter() { cv.visitInsn(Constants.MONITORENTER); } public void monitorexit() { cv.visitInsn(Constants.MONITOREXIT); } public void math(int op, Type type) { cv.visitInsn(type.getOpcode(op)); } public void array_load(Type type) { cv.visitInsn(type.getOpcode(Constants.IALOAD)); } public void array_store(Type type) { cv.visitInsn(type.getOpcode(Constants.IASTORE)); } /** * Casts from one primitive numeric type to another */ public void cast_numeric(Type from, Type to) { if (from != to) { if (from == Type.DOUBLE_TYPE) { if (to == Type.FLOAT_TYPE) { cv.visitInsn(Constants.D2F); } else if (to == Type.LONG_TYPE) { cv.visitInsn(Constants.D2L); } else { cv.visitInsn(Constants.D2I); cast_numeric(Type.INT_TYPE, to); } } else if (from == Type.FLOAT_TYPE) { if (to == Type.DOUBLE_TYPE) { cv.visitInsn(Constants.F2D); } else if (to == Type.LONG_TYPE) { cv.visitInsn(Constants.F2L); } else { cv.visitInsn(Constants.F2I); cast_numeric(Type.INT_TYPE, to); } } else if (from == Type.LONG_TYPE) { if (to == Type.DOUBLE_TYPE) { cv.visitInsn(Constants.L2D); } else if (to == Type.FLOAT_TYPE) { cv.visitInsn(Constants.L2F); } else { cv.visitInsn(Constants.L2I); cast_numeric(Type.INT_TYPE, to); } } else { if (to == Type.BYTE_TYPE) { cv.visitInsn(Constants.I2B); } else if (to == Type.CHAR_TYPE) { cv.visitInsn(Constants.I2C); } else if (to == Type.DOUBLE_TYPE) { cv.visitInsn(Constants.I2D); } else if (to == Type.FLOAT_TYPE) { cv.visitInsn(Constants.I2F); } else if (to == Type.LONG_TYPE) { cv.visitInsn(Constants.I2L); } else if (to == Type.SHORT_TYPE) { cv.visitInsn(Constants.I2S); } } } } public void push(int i) { if (i < -1) { cv.visitLdcInsn(new Integer(i)); } else if (i <= 5) { cv.visitInsn(TypeUtils.ICONST(i)); } else if (i <= Byte.MAX_VALUE) { cv.visitIntInsn(Constants.BIPUSH, i); } else if (i <= Short.MAX_VALUE) { cv.visitIntInsn(Constants.SIPUSH, i); } else { cv.visitLdcInsn(new Integer(i)); } } public void push(long value) { if (value == 0L || value == 1L) { cv.visitInsn(TypeUtils.LCONST(value)); } else { cv.visitLdcInsn(new Long(value)); } } public void push(float value) { if (value == 0f || value == 1f || value == 2f) { cv.visitInsn(TypeUtils.FCONST(value)); } else { cv.visitLdcInsn(new Float(value)); } } public void push(double value) { if (value == 0d || value == 1d) { cv.visitInsn(TypeUtils.DCONST(value)); } else { cv.visitLdcInsn(new Double(value)); } } public void push(String value) { cv.visitLdcInsn(value); } public void newarray() { newarray(Constants.TYPE_OBJECT); } public void newarray(Type type) { if (TypeUtils.isPrimitive(type)) { cv.visitIntInsn(Constants.NEWARRAY, TypeUtils.NEWARRAY(type)); } else { emit_type(Constants.ANEWARRAY, type); } } public void arraylength() { cv.visitInsn(Constants.ARRAYLENGTH); } public void load_this() { if (TypeUtils.isStatic(state.access)) { throw new IllegalStateException("no 'this' pointer within static method"); } cv.visitVarInsn(Constants.ALOAD, 0); } /** * Pushes all of the arguments of the current method onto the stack. */ public void load_args() { load_args(0, state.argumentTypes.length); } /** * Pushes the specified argument of the current method onto the stack. * @param index the zero-based index into the argument list */ public void load_arg(int index) { load_local(state.argumentTypes[index], state.localOffset + skipArgs(index)); } // zero-based (see load_this) public void load_args(int fromArg, int count) { int pos = state.localOffset + skipArgs(fromArg); for (int i = 0; i < count; i++) { Type t = state.argumentTypes[fromArg + i]; load_local(t, pos); pos += t.getSize(); } } private int skipArgs(int numArgs) { int amount = 0; for (int i = 0; i < numArgs; i++) { amount += state.argumentTypes[i].getSize(); } return amount; } private void load_local(Type t, int pos) { // TODO: make t == null ok? cv.visitVarInsn(t.getOpcode(Constants.ILOAD), pos); } private void store_local(Type t, int pos) { // TODO: make t == null ok? cv.visitVarInsn(t.getOpcode(Constants.ISTORE), pos); } public void iinc(Local local, int amount) { cv.visitIincInsn(local.getIndex(), amount); } public void store_local(Local local) { store_local(local.getType(), local.getIndex()); } public void load_local(Local local) { load_local(local.getType(), local.getIndex()); } public void return_value() { cv.visitInsn(state.sig.getReturnType().getOpcode(Constants.IRETURN)); } public void getfield(String name) { ClassEmitter.FieldInfo info = ce.getFieldInfo(name); int opcode = TypeUtils.isStatic(info.access) ? Constants.GETSTATIC : Constants.GETFIELD; emit_field(opcode, ce.getClassType(), name, info.type); } public void putfield(String name) { ClassEmitter.FieldInfo info = ce.getFieldInfo(name); int opcode = TypeUtils.isStatic(info.access) ? Constants.PUTSTATIC : Constants.PUTFIELD; emit_field(opcode, ce.getClassType(), name, info.type); } public void super_getfield(String name, Type type) { emit_field(Constants.GETFIELD, ce.getSuperType(), name, type); } public void super_putfield(String name, Type type) { emit_field(Constants.PUTFIELD, ce.getSuperType(), name, type); } public void super_getstatic(String name, Type type) { emit_field(Constants.GETSTATIC, ce.getSuperType(), name, type); } public void super_putstatic(String name, Type type) { emit_field(Constants.PUTSTATIC, ce.getSuperType(), name, type); } public void getfield(Type owner, String name, Type type) { emit_field(Constants.GETFIELD, owner, name, type); } public void putfield(Type owner, String name, Type type) { emit_field(Constants.PUTFIELD, owner, name, type); } public void getstatic(Type owner, String name, Type type) { emit_field(Constants.GETSTATIC, owner, name, type); } public void putstatic(Type owner, String name, Type type) { emit_field(Constants.PUTSTATIC, owner, name, type); } // package-protected for EmitUtils, try to fix void emit_field(int opcode, Type ctype, String name, Type ftype) { cv.visitFieldInsn(opcode, ctype.getInternalName(), name, ftype.getDescriptor()); } public void super_invoke() { super_invoke(state.sig); } public void super_invoke(Signature sig) { emit_invoke(Constants.INVOKESPECIAL, ce.getSuperType(), sig); } public void invoke_constructor(Type type) { invoke_constructor(type, CSTRUCT_NULL); } public void super_invoke_constructor() { invoke_constructor(ce.getSuperType()); } public void invoke_constructor_this() { invoke_constructor(ce.getClassType()); } private void emit_invoke(int opcode, Type type, Signature sig) { if (sig.getName().equals(Constants.CONSTRUCTOR_NAME) && ((opcode == Constants.INVOKEVIRTUAL) || (opcode == Constants.INVOKESTATIC))) { // TODO: error } cv.visitMethodInsn(opcode, type.getInternalName(), sig.getName(), sig.getDescriptor()); } public void invoke_interface(Type owner, Signature sig) { emit_invoke(Constants.INVOKEINTERFACE, owner, sig); } public void invoke_virtual(Type owner, Signature sig) { emit_invoke(Constants.INVOKEVIRTUAL, owner, sig); } public void invoke_static(Type owner, Signature sig) { emit_invoke(Constants.INVOKESTATIC, owner, sig); } public void invoke_virtual_this(Signature sig) { invoke_virtual(ce.getClassType(), sig); } public void invoke_static_this(Signature sig) { invoke_static(ce.getClassType(), sig); } public void invoke_constructor(Type type, Signature sig) { emit_invoke(Constants.INVOKESPECIAL, type, sig); } public void invoke_constructor_this(Signature sig) { invoke_constructor(ce.getClassType(), sig); } public void super_invoke_constructor(Signature sig) { invoke_constructor(ce.getSuperType(), sig); } public void new_instance_this() { new_instance(ce.getClassType()); } public void new_instance(Type type) { emit_type(Constants.NEW, type); } private void emit_type(int opcode, Type type) { String desc; if (TypeUtils.isArray(type)) { desc = type.getDescriptor(); } else { desc = type.getInternalName(); } cv.visitTypeInsn(opcode, desc); } public void aaload(int index) { push(index); aaload(); } public void aaload() { cv.visitInsn(Constants.AALOAD); } public void aastore() { cv.visitInsn(Constants.AASTORE); } public void athrow() { cv.visitInsn(Constants.ATHROW); } public Label make_label() { return new Label(); } public Local make_local() { return make_local(Constants.TYPE_OBJECT); } public Local make_local(Type type) { return new Local(nextLocal(type.getSize()), type); } public void checkcast_this() { checkcast(ce.getClassType()); } public void checkcast(Type type) { if (!type.equals(Constants.TYPE_OBJECT)) { emit_type(Constants.CHECKCAST, type); } } public void instance_of(Type type) { emit_type(Constants.INSTANCEOF, type); } public void instance_of_this() { instance_of(ce.getClassType()); } public void process_switch(int[] keys, ProcessSwitchCallback callback) { float density; if (keys.length == 0) { density = 0; } else { density = (float)keys.length / (keys[keys.length - 1] - keys[0] + 1); } process_switch(keys, callback, density >= 0.5f); } public void process_switch(int[] keys, ProcessSwitchCallback callback, boolean useTable) { if (!isSorted(keys)) throw new IllegalArgumentException("keys to switch must be sorted ascending"); Label def = make_label(); Label end = make_label(); try { if (keys.length > 0) { int len = keys.length; int min = keys[0]; int max = keys[len - 1]; int range = max - min + 1; if (useTable) { Label[] labels = new Label[range]; Arrays.fill(labels, def); for (int i = 0; i < len; i++) { labels[keys[i] - min] = make_label(); } cv.visitTableSwitchInsn(min, max, def, labels); for (int i = 0; i < range; i++) { Label label = labels[i]; if (label != def) { mark(label); callback.processCase(i + min, end); } } } else { Label[] labels = new Label[len]; for (int i = 0; i < len; i++) { labels[i] = make_label(); } cv.visitLookupSwitchInsn(def, keys, labels); for (int i = 0; i < len; i++) { mark(labels[i]); callback.processCase(keys[i], end); } } } mark(def); callback.processDefault(); mark(end); } catch (RuntimeException e) { throw e; } catch (Error e) { throw e; } catch (Exception e) { throw new CodeGenerationException(e); } } private static boolean isSorted(int[] keys) { for (int i = 1; i < keys.length; i++) { if (keys[i] < keys[i - 1]) return false; } return true; } public void mark(Label label) { cv.visitLabel(label); } Label mark() { Label label = make_label(); cv.visitLabel(label); return label; } public void push(boolean value) { push(value ? 1 : 0); } /** * Toggles the integer on the top of the stack from 1 to 0 or vice versa */ public void not() { push(1); math(XOR, Type.INT_TYPE); } public void throw_exception(Type type, String msg) { new_instance(type); dup(); push(msg); invoke_constructor(type, CSTRUCT_STRING); athrow(); } /** * If the argument is a primitive class, replaces the primitive value * on the top of the stack with the wrapped (Object) equivalent. For * example, char -> Character. * If the class is Void, a null is pushed onto the stack instead. * @param type the class indicating the current type of the top stack value */ public void box(Type type) { if (TypeUtils.isPrimitive(type)) { if (type == Type.VOID_TYPE) { aconst_null(); } else { Type boxed = TypeUtils.getBoxedType(type); new_instance(boxed); if (type.getSize() == 2) { // Pp -> Ppo -> oPpo -> ooPpo -> ooPp -> o dup_x2(); dup_x2(); pop(); } else { // p -> po -> opo -> oop -> o dup_x1(); swap(); } invoke_constructor(boxed, new Signature(Constants.CONSTRUCTOR_NAME, Type.VOID_TYPE, new Type[]{ type })); } } } /** * If the argument is a primitive class, replaces the object * on the top of the stack with the unwrapped (primitive) * equivalent. For example, Character -> char. * @param type the class indicating the desired type of the top stack value * @return true if the value was unboxed */ public void unbox(Type type) { Type t = Constants.TYPE_NUMBER; Signature sig = null; switch (type.getSort()) { case Type.VOID: return; case Type.CHAR: t = Constants.TYPE_CHARACTER; sig = CHAR_VALUE; break; case Type.BOOLEAN: t = Constants.TYPE_BOOLEAN; sig = BOOLEAN_VALUE; break; case Type.DOUBLE: sig = DOUBLE_VALUE; break; case Type.FLOAT: sig = FLOAT_VALUE; break; case Type.LONG: sig = LONG_VALUE; break; case Type.INT: case Type.SHORT: case Type.BYTE: sig = INT_VALUE; } if (sig == null) { checkcast(type); } else { checkcast(t); invoke_virtual(t, sig); } } /** * Allocates and fills an Object[] array with the arguments to the * current method. Primitive values are inserted as their boxed * (Object) equivalents. */ public void create_arg_array() { /* generates: Object[] args = new Object[]{ arg1, new Integer(arg2) }; */ push(state.argumentTypes.length); newarray(); for (int i = 0; i < state.argumentTypes.length; i++) { dup(); push(i); load_arg(i); box(state.argumentTypes[i]); aastore(); } } /** * Pushes a zero onto the stack if the argument is a primitive class, or a null otherwise. */ public void zero_or_null(Type type) { if (TypeUtils.isPrimitive(type)) { switch (type.getSort()) { case Type.DOUBLE: push(0d); break; case Type.LONG: push(0L); break; case Type.FLOAT: push(0f); break; case Type.VOID: aconst_null(); default: push(0); } } else { aconst_null(); } } /** * Unboxes the object on the top of the stack. If the object is null, the * unboxed primitive value becomes zero. */ public void unbox_or_zero(Type type) { if (TypeUtils.isPrimitive(type)) { if (type != Type.VOID_TYPE) { Label nonNull = make_label(); Label end = make_label(); dup(); ifnonnull(nonNull); pop(); zero_or_null(type); goTo(end); mark(nonNull); unbox(type); mark(end); } } else { checkcast(type); } } public void visitMaxs(int maxStack, int maxLocals) { if (!TypeUtils.isAbstract(state.access)) { cv.visitMaxs(0, 0); } } public void invoke(Method method) { Class declaring = method.getDeclaringClass(); Type owner = Type.getType(declaring); Signature sig = TypeUtils.getSignature(method); if (declaring.isInterface()) { invoke_interface(owner, sig); } else if (TypeUtils.isStatic(method.getModifiers())) { invoke_static(owner, sig); } else { invoke_virtual(owner, sig); } } public void define_attribute(Attribu... [truncated message content] |