use of org.objectweb.asm.tree.InsnNode in project MinecraftForge by MinecraftForge.
the class EventSubscriptionTransformer method buildEvents.
private boolean buildEvents(ClassNode classNode) throws Exception {
// Yes, this recursively loads classes until we get this base class. THIS IS NOT A ISSUE. Coremods should handle re-entry just fine.
// If they do not this a COREMOD issue NOT a Forge/LaunchWrapper issue.
Class<?> parent = this.getClass().getClassLoader().loadClass(classNode.superName.replace('/', '.'));
if (!Event.class.isAssignableFrom(parent)) {
return false;
}
//Class<?> listenerListClazz = Class.forName("net.minecraftforge.fml.common.eventhandler.ListenerList", false, getClass().getClassLoader());
Type tList = Type.getType("Lnet/minecraftforge/fml/common/eventhandler/ListenerList;");
boolean edited = false;
boolean hasSetup = false;
boolean hasGetListenerList = false;
boolean hasDefaultCtr = false;
boolean hasCancelable = false;
boolean hasResult = false;
String voidDesc = Type.getMethodDescriptor(VOID_TYPE);
String boolDesc = Type.getMethodDescriptor(BOOLEAN_TYPE);
String listDesc = tList.getDescriptor();
String listDescM = Type.getMethodDescriptor(tList);
for (MethodNode method : classNode.methods) {
if (method.name.equals("setup") && method.desc.equals(voidDesc) && (method.access & ACC_PROTECTED) == ACC_PROTECTED)
hasSetup = true;
if ((method.access & ACC_PUBLIC) == ACC_PUBLIC) {
if (method.name.equals("getListenerList") && method.desc.equals(listDescM))
hasGetListenerList = true;
if (method.name.equals("isCancelable") && method.desc.equals(boolDesc))
hasCancelable = true;
if (method.name.equals("hasResult") && method.desc.equals(boolDesc))
hasResult = true;
}
if (method.name.equals("<init>") && method.desc.equals(voidDesc))
hasDefaultCtr = true;
}
if (classNode.visibleAnnotations != null) {
for (AnnotationNode node : classNode.visibleAnnotations) {
if (!hasResult && node.desc.equals("Lnet/minecraftforge/fml/common/eventhandler/Event$HasResult;")) {
/* Add:
* public boolean hasResult()
* {
* return true;
* }
*/
MethodNode method = new MethodNode(ACC_PUBLIC, "hasResult", boolDesc, null, null);
method.instructions.add(new InsnNode(ICONST_1));
method.instructions.add(new InsnNode(IRETURN));
classNode.methods.add(method);
edited = true;
} else if (!hasCancelable && node.desc.equals("Lnet/minecraftforge/fml/common/eventhandler/Cancelable;")) {
/* Add:
* public boolean isCancelable()
* {
* return true;
* }
*/
MethodNode method = new MethodNode(ACC_PUBLIC, "isCancelable", boolDesc, null, null);
method.instructions.add(new InsnNode(ICONST_1));
method.instructions.add(new InsnNode(IRETURN));
classNode.methods.add(method);
edited = true;
}
}
}
if (hasSetup) {
if (!hasGetListenerList)
throw new RuntimeException("Event class defines setup() but does not define getListenerList! " + classNode.name);
else
return edited;
}
Type tSuper = Type.getType(classNode.superName);
//Add private static ListenerList LISTENER_LIST
classNode.fields.add(new FieldNode(ACC_PRIVATE | ACC_STATIC, "LISTENER_LIST", listDesc, null, null));
/*Add:
* public <init>()
* {
* super();
* }
*/
if (!hasDefaultCtr) {
MethodNode method = new MethodNode(ACC_PUBLIC, "<init>", voidDesc, null, null);
method.instructions.add(new VarInsnNode(ALOAD, 0));
method.instructions.add(new MethodInsnNode(INVOKESPECIAL, tSuper.getInternalName(), "<init>", voidDesc, false));
method.instructions.add(new InsnNode(RETURN));
classNode.methods.add(method);
}
/*Add:
* protected void setup()
* {
* super.setup();
* if (LISTENER_LIST != NULL)
* {
* return;
* }
* LISTENER_LIST = new ListenerList(super.getListenerList());
* }
*/
MethodNode method = new MethodNode(ACC_PROTECTED, "setup", voidDesc, null, null);
method.instructions.add(new VarInsnNode(ALOAD, 0));
method.instructions.add(new MethodInsnNode(INVOKESPECIAL, tSuper.getInternalName(), "setup", voidDesc, false));
method.instructions.add(new FieldInsnNode(GETSTATIC, classNode.name, "LISTENER_LIST", listDesc));
LabelNode initListener = new LabelNode();
method.instructions.add(new JumpInsnNode(IFNULL, initListener));
method.instructions.add(new InsnNode(RETURN));
method.instructions.add(initListener);
method.instructions.add(new FrameNode(F_SAME, 0, null, 0, null));
method.instructions.add(new TypeInsnNode(NEW, tList.getInternalName()));
method.instructions.add(new InsnNode(DUP));
method.instructions.add(new VarInsnNode(ALOAD, 0));
method.instructions.add(new MethodInsnNode(INVOKESPECIAL, tSuper.getInternalName(), "getListenerList", listDescM, false));
method.instructions.add(new MethodInsnNode(INVOKESPECIAL, tList.getInternalName(), "<init>", getMethodDescriptor(VOID_TYPE, tList), false));
method.instructions.add(new FieldInsnNode(PUTSTATIC, classNode.name, "LISTENER_LIST", listDesc));
method.instructions.add(new InsnNode(RETURN));
classNode.methods.add(method);
/*Add:
* public ListenerList getListenerList()
* {
* return this.LISTENER_LIST;
* }
*/
method = new MethodNode(ACC_PUBLIC, "getListenerList", listDescM, null, null);
method.instructions.add(new FieldInsnNode(GETSTATIC, classNode.name, "LISTENER_LIST", listDesc));
method.instructions.add(new InsnNode(ARETURN));
classNode.methods.add(method);
return true;
}
use of org.objectweb.asm.tree.InsnNode in project jphp by jphp-compiler.
the class ReturnCompiler method write.
@Override
public void write(ReturnStmtToken token) {
if (token.getValue() != null && method.getGeneratorEntity() != null) {
env.error(token.toTraceInfo(compiler.getContext()), ErrorType.E_ERROR, "Generators cannot return values using \"return\"");
}
Memory result = Memory.NULL;
boolean isImmutable = method.getEntity().isImmutable();
if (token.getValue() != null)
result = expr.writeExpression(token.getValue(), true, true);
if (result != null) {
if (isImmutable) {
if (method.getEntity().getResult() == null)
method.getEntity().setResult(result);
}
expr.writePushMemory(result);
} else {
method.getEntity().setImmutable(false);
}
if (expr.stackEmpty(false))
expr.writePushNull();
else
expr.writePopBoxing(false);
if (method.getEntity().isReturnReference()) {
expr.writePushDup();
expr.writePushEnv();
expr.writePushTraceInfo(token);
expr.writeSysStaticCall(InvokeHelper.class, "checkReturnReference", void.class, Memory.class, Environment.class, TraceInfo.class);
} else
expr.writePopImmutable();
if (!method.getTryStack().empty()) {
LocalVariable variable = method.getLocalVariable("~result~");
if (variable == null)
variable = method.addLocalVariable("~result~", null, Memory.class);
expr.writeVarStore(variable, false, false);
add(new JumpInsnNode(GOTO, method.getTryStack().peek().getReturnLabel()));
} else {
add(new InsnNode(ARETURN));
//removeStackFrame();
expr.stackPop();
}
}
use of org.objectweb.asm.tree.InsnNode in project pinpoint by naver.
the class ASMMethodVariables method box.
void box(final InsnList instructions, Type type) {
if (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY) {
return;
}
if (type == Type.VOID_TYPE) {
// push null
instructions.add(new InsnNode(Opcodes.ACONST_NULL));
} else {
Type boxed = getBoxedType(type);
// new instance.
newInstance(instructions, boxed);
if (type.getSize() == 2) {
// Pp -> Ppo -> oPpo -> ooPpo -> ooPp -> o
// dupX2
dupX2(instructions);
// dupX2
dupX2(instructions);
// pop
pop(instructions);
} else {
// p -> po -> opo -> oop -> o
// dupX1
dupX1(instructions);
// swap
swap(instructions);
}
invokeConstructor(instructions, boxed, new Method("<init>", Type.VOID_TYPE, new Type[] { type }));
}
}
use of org.objectweb.asm.tree.InsnNode in project pinpoint by naver.
the class ASMClassNodeAdapter method addSetterMethod.
public void addSetterMethod(final String methodName, final ASMFieldNodeAdapter fieldNode) {
if (methodName == null || fieldNode == null) {
throw new IllegalArgumentException("method name or fieldNode annotation must not be null.");
}
// void is V.
final String desc = "(" + fieldNode.getDesc() + ")V";
final MethodNode methodNode = new MethodNode(Opcodes.ACC_PUBLIC, methodName, desc, null, null);
if (methodNode.instructions == null) {
methodNode.instructions = new InsnList();
}
final InsnList instructions = methodNode.instructions;
// load this.
instructions.add(new VarInsnNode(Opcodes.ALOAD, 0));
final Type type = Type.getType(fieldNode.getDesc());
// put field.
instructions.add(new VarInsnNode(type.getOpcode(Opcodes.ILOAD), 1));
instructions.add(new FieldInsnNode(Opcodes.PUTFIELD, classNode.name, fieldNode.getName(), fieldNode.getDesc()));
// return.
instructions.add(new InsnNode(Opcodes.RETURN));
if (this.classNode.methods == null) {
this.classNode.methods = new ArrayList<MethodNode>();
}
this.classNode.methods.add(methodNode);
}
use of org.objectweb.asm.tree.InsnNode in project robolectric by robolectric.
the class SandboxClassLoader method box.
public static void box(final Type type, ListIterator<AbstractInsnNode> instructions) {
if (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY) {
return;
}
if (type == Type.VOID_TYPE) {
instructions.add(new InsnNode(ACONST_NULL));
} else {
Type boxed = getBoxedType(type);
instructions.add(new TypeInsnNode(NEW, boxed.getInternalName()));
if (type.getSize() == 2) {
// Pp -> Ppo -> oPpo -> ooPpo -> ooPp -> o
instructions.add(new InsnNode(DUP_X2));
instructions.add(new InsnNode(DUP_X2));
instructions.add(new InsnNode(POP));
} else {
// p -> po -> opo -> oop -> o
instructions.add(new InsnNode(DUP_X1));
instructions.add(new InsnNode(SWAP));
}
instructions.add(new MethodInsnNode(INVOKESPECIAL, boxed.getInternalName(), "<init>", "(" + type.getDescriptor() + ")V"));
}
}
Aggregations