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");
}
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();
}
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();
}
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();
}
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();
}
Aggregations