Search in sources :

Example 1 with Label

use of org.springframework.asm.Label in project spring-framework by spring-projects.

the class Operator method generateComparisonCode.

/** 
	 * Numeric comparison operators share very similar generated code, only differing in 
	 * two comparison instructions.
	 */
protected void generateComparisonCode(MethodVisitor mv, CodeFlow cf, int compInstruction1, int compInstruction2) {
    String leftDesc = getLeftOperand().exitTypeDescriptor;
    String rightDesc = getRightOperand().exitTypeDescriptor;
    boolean unboxLeft = !CodeFlow.isPrimitive(leftDesc);
    boolean unboxRight = !CodeFlow.isPrimitive(rightDesc);
    DescriptorComparison dc = DescriptorComparison.checkNumericCompatibility(leftDesc, rightDesc, this.leftActualDescriptor, this.rightActualDescriptor);
    // CodeFlow.toPrimitiveTargetDesc(leftDesc);
    char targetType = dc.compatibleType;
    cf.enterCompilationScope();
    getLeftOperand().generateCode(mv, cf);
    cf.exitCompilationScope();
    if (unboxLeft) {
        CodeFlow.insertUnboxInsns(mv, targetType, leftDesc);
    }
    cf.enterCompilationScope();
    getRightOperand().generateCode(mv, cf);
    cf.exitCompilationScope();
    if (unboxRight) {
        CodeFlow.insertUnboxInsns(mv, targetType, rightDesc);
    }
    // assert: SpelCompiler.boxingCompatible(leftDesc, rightDesc)
    Label elseTarget = new Label();
    Label endOfIf = new Label();
    if (targetType == 'D') {
        mv.visitInsn(DCMPG);
        mv.visitJumpInsn(compInstruction1, elseTarget);
    } else if (targetType == 'F') {
        mv.visitInsn(FCMPG);
        mv.visitJumpInsn(compInstruction1, elseTarget);
    } else if (targetType == 'J') {
        mv.visitInsn(LCMP);
        mv.visitJumpInsn(compInstruction1, elseTarget);
    } else if (targetType == 'I') {
        mv.visitJumpInsn(compInstruction2, elseTarget);
    } else {
        throw new IllegalStateException("Unexpected descriptor " + leftDesc);
    }
    // Other numbers are not yet supported (isCompilable will not have returned true)
    mv.visitInsn(ICONST_1);
    mv.visitJumpInsn(GOTO, endOfIf);
    mv.visitLabel(elseTarget);
    mv.visitInsn(ICONST_0);
    mv.visitLabel(endOfIf);
    cf.pushDescriptor("Z");
}
Also used : Label(org.springframework.asm.Label)

Example 2 with Label

use of org.springframework.asm.Label in project spring-framework by spring-projects.

the class Enhancer method emitMethods.

private void emitMethods(final ClassEmitter ce, List methods, List actualMethods) {
    CallbackGenerator[] generators = CallbackInfo.getGenerators(callbackTypes);
    Map groups = new HashMap();
    final Map indexes = new HashMap();
    final Map originalModifiers = new HashMap();
    final Map positions = CollectionUtils.getIndexMap(methods);
    final Map declToBridge = new HashMap();
    Iterator it1 = methods.iterator();
    Iterator it2 = (actualMethods != null) ? actualMethods.iterator() : null;
    while (it1.hasNext()) {
        MethodInfo method = (MethodInfo) it1.next();
        Method actualMethod = (it2 != null) ? (Method) it2.next() : null;
        int index = filter.accept(actualMethod);
        if (index >= callbackTypes.length) {
            throw new IllegalArgumentException("Callback filter returned an index that is too large: " + index);
        }
        originalModifiers.put(method, (actualMethod != null ? actualMethod.getModifiers() : method.getModifiers()));
        indexes.put(method, index);
        List group = (List) groups.get(generators[index]);
        if (group == null) {
            groups.put(generators[index], group = new ArrayList(methods.size()));
        }
        group.add(method);
        // so that we can look up all the bridge methods in one pass for a class.
        if (TypeUtils.isBridge(actualMethod.getModifiers())) {
            Set bridges = (Set) declToBridge.get(actualMethod.getDeclaringClass());
            if (bridges == null) {
                bridges = new HashSet();
                declToBridge.put(actualMethod.getDeclaringClass(), bridges);
            }
            bridges.add(method.getSignature());
        }
    }
    final Map bridgeToTarget = new BridgeMethodResolver(declToBridge, getClassLoader()).resolveAll();
    Set seenGen = new HashSet();
    CodeEmitter se = ce.getStaticHook();
    se.new_instance(THREAD_LOCAL);
    se.dup();
    se.invoke_constructor(THREAD_LOCAL, CSTRUCT_NULL);
    se.putfield(THREAD_CALLBACKS_FIELD);
    final Object[] state = new Object[1];
    CallbackGenerator.Context context = new CallbackGenerator.Context() {

        public ClassLoader getClassLoader() {
            return Enhancer.this.getClassLoader();
        }

        public int getOriginalModifiers(MethodInfo method) {
            return ((Integer) originalModifiers.get(method)).intValue();
        }

        public int getIndex(MethodInfo method) {
            return ((Integer) indexes.get(method)).intValue();
        }

        public void emitCallback(CodeEmitter e, int index) {
            emitCurrentCallback(e, index);
        }

        public Signature getImplSignature(MethodInfo method) {
            return rename(method.getSignature(), ((Integer) positions.get(method)).intValue());
        }

        public void emitLoadArgsAndInvoke(CodeEmitter e, MethodInfo method) {
            // If this is a bridge and we know the target was called from invokespecial,
            // then we need to invoke_virtual w/ the bridge target instead of doing
            // a super, because super may itself be using super, which would bypass
            // any proxies on the target.
            Signature bridgeTarget = (Signature) bridgeToTarget.get(method.getSignature());
            if (bridgeTarget != null) {
                // checkcast each argument against the target's argument types
                for (int i = 0; i < bridgeTarget.getArgumentTypes().length; i++) {
                    e.load_arg(i);
                    Type target = bridgeTarget.getArgumentTypes()[i];
                    if (!target.equals(method.getSignature().getArgumentTypes()[i])) {
                        e.checkcast(target);
                    }
                }
                e.invoke_virtual_this(bridgeTarget);
                Type retType = method.getSignature().getReturnType();
                // method.)
                if (!retType.equals(bridgeTarget.getReturnType())) {
                    e.checkcast(retType);
                }
            } else {
                e.load_args();
                e.super_invoke(method.getSignature());
            }
        }

        public CodeEmitter beginMethod(ClassEmitter ce, MethodInfo method) {
            CodeEmitter e = EmitUtils.begin_method(ce, method);
            if (!interceptDuringConstruction && !TypeUtils.isAbstract(method.getModifiers())) {
                Label constructed = e.make_label();
                e.load_this();
                e.getfield(CONSTRUCTED_FIELD);
                e.if_jump(CodeEmitter.NE, constructed);
                e.load_this();
                e.load_args();
                e.super_invoke();
                e.return_value();
                e.mark(constructed);
            }
            return e;
        }
    };
    for (int i = 0; i < callbackTypes.length; i++) {
        CallbackGenerator gen = generators[i];
        if (!seenGen.contains(gen)) {
            seenGen.add(gen);
            final List fmethods = (List) groups.get(gen);
            if (fmethods != null) {
                try {
                    gen.generate(ce, context, fmethods);
                    gen.generateStatic(se, context, fmethods);
                } catch (RuntimeException x) {
                    throw x;
                } catch (Exception x) {
                    throw new CodeGenerationException(x);
                }
            }
        }
    }
    se.return_value();
    se.end_method();
}
Also used : HashSet(java.util.HashSet) Set(java.util.Set) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) ClassEmitter(org.springframework.cglib.core.ClassEmitter) Label(org.springframework.asm.Label) CodeGenerationException(org.springframework.cglib.core.CodeGenerationException) Iterator(java.util.Iterator) ArrayList(java.util.ArrayList) List(java.util.List) HashSet(java.util.HashSet) Method(java.lang.reflect.Method) CodeGenerationException(org.springframework.cglib.core.CodeGenerationException) InvocationTargetException(java.lang.reflect.InvocationTargetException) CodeEmitter(org.springframework.cglib.core.CodeEmitter) Type(org.springframework.asm.Type) Signature(org.springframework.cglib.core.Signature) MethodInfo(org.springframework.cglib.core.MethodInfo) HashMap(java.util.HashMap) Map(java.util.Map)

Example 3 with Label

use of org.springframework.asm.Label in project spring-framework by spring-projects.

the class Enhancer method emitNewInstanceMultiarg.

private void emitNewInstanceMultiarg(ClassEmitter ce, List constructors) {
    final CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, MULTIARG_NEW_INSTANCE, null);
    final Type thisType = getThisType(e);
    e.load_arg(2);
    e.invoke_static(thisType, SET_THREAD_CALLBACKS, false);
    e.new_instance(thisType);
    e.dup();
    e.load_arg(0);
    EmitUtils.constructor_switch(e, constructors, new ObjectSwitchCallback() {

        public void processCase(Object key, Label end) {
            MethodInfo constructor = (MethodInfo) key;
            Type[] types = constructor.getSignature().getArgumentTypes();
            for (int i = 0; i < types.length; i++) {
                e.load_arg(1);
                e.push(i);
                e.aaload();
                e.unbox(types[i]);
            }
            e.invoke_constructor(thisType, constructor.getSignature());
            e.goTo(end);
        }

        public void processDefault() {
            e.throw_exception(ILLEGAL_ARGUMENT_EXCEPTION, "Constructor not found");
        }
    });
    e.aconst_null();
    e.invoke_static(thisType, SET_THREAD_CALLBACKS, false);
    e.return_value();
    e.end_method();
}
Also used : CodeEmitter(org.springframework.cglib.core.CodeEmitter) Type(org.springframework.asm.Type) Label(org.springframework.asm.Label) MethodInfo(org.springframework.cglib.core.MethodInfo) ObjectSwitchCallback(org.springframework.cglib.core.ObjectSwitchCallback)

Example 4 with Label

use of org.springframework.asm.Label in project spring-framework by spring-projects.

the class Enhancer method emitBindCallbacks.

private void emitBindCallbacks(ClassEmitter ce) {
    CodeEmitter e = ce.begin_method(Constants.PRIVATE_FINAL_STATIC, BIND_CALLBACKS, null);
    Local me = e.make_local();
    e.load_arg(0);
    e.checkcast_this();
    e.store_local(me);
    Label end = e.make_label();
    e.load_local(me);
    e.getfield(BOUND_FIELD);
    e.if_jump(CodeEmitter.NE, end);
    e.load_local(me);
    e.push(1);
    e.putfield(BOUND_FIELD);
    e.getfield(THREAD_CALLBACKS_FIELD);
    e.invoke_virtual(THREAD_LOCAL, THREAD_LOCAL_GET);
    e.dup();
    Label found_callback = e.make_label();
    e.ifnonnull(found_callback);
    e.pop();
    e.getfield(STATIC_CALLBACKS_FIELD);
    e.dup();
    e.ifnonnull(found_callback);
    e.pop();
    e.goTo(end);
    e.mark(found_callback);
    e.checkcast(CALLBACK_ARRAY);
    e.load_local(me);
    e.swap();
    for (int i = callbackTypes.length - 1; i >= 0; i--) {
        if (i != 0) {
            e.dup2();
        }
        e.aaload(i);
        e.checkcast(callbackTypes[i]);
        e.putfield(getCallbackField(i));
    }
    e.mark(end);
    e.return_value();
    e.end_method();
}
Also used : CodeEmitter(org.springframework.cglib.core.CodeEmitter) Label(org.springframework.asm.Label) Local(org.springframework.cglib.core.Local)

Example 5 with Label

use of org.springframework.asm.Label in project spring-framework by spring-projects.

the class Enhancer method emitSetCallback.

private void emitSetCallback(ClassEmitter ce, int[] keys) {
    final CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, SET_CALLBACK, null);
    e.load_arg(0);
    e.process_switch(keys, new ProcessSwitchCallback() {

        public void processCase(int key, Label end) {
            e.load_this();
            e.load_arg(1);
            e.checkcast(callbackTypes[key]);
            e.putfield(getCallbackField(key));
            e.goTo(end);
        }

        public void processDefault() {
        // TODO: error?
        }
    });
    e.return_value();
    e.end_method();
}
Also used : CodeEmitter(org.springframework.cglib.core.CodeEmitter) ProcessSwitchCallback(org.springframework.cglib.core.ProcessSwitchCallback) Label(org.springframework.asm.Label)

Aggregations

Label (org.springframework.asm.Label)14 CodeEmitter (org.springframework.cglib.core.CodeEmitter)5 Method (java.lang.reflect.Method)2 Type (org.springframework.asm.Type)2 MethodInfo (org.springframework.cglib.core.MethodInfo)2 ProcessSwitchCallback (org.springframework.cglib.core.ProcessSwitchCallback)2 InvocationTargetException (java.lang.reflect.InvocationTargetException)1 ArrayList (java.util.ArrayList)1 HashMap (java.util.HashMap)1 HashSet (java.util.HashSet)1 Iterator (java.util.Iterator)1 List (java.util.List)1 Map (java.util.Map)1 Set (java.util.Set)1 ClassEmitter (org.springframework.cglib.core.ClassEmitter)1 CodeGenerationException (org.springframework.cglib.core.CodeGenerationException)1 Local (org.springframework.cglib.core.Local)1 ObjectSwitchCallback (org.springframework.cglib.core.ObjectSwitchCallback)1 Signature (org.springframework.cglib.core.Signature)1 EvaluationContext (org.springframework.expression.EvaluationContext)1