List of usage examples for org.objectweb.asm Opcodes DUP
int DUP
To view the source code for org.objectweb.asm Opcodes DUP.
Click Source Link
From source file:pl.clareo.coroutines.core.ClassTransformer.java
License:Apache License
@SuppressWarnings("unchecked") void transform() { for (MethodNode coroutine : coroutines) { if (log.isLoggable(Level.FINEST)) { log.finest("Generating method for coroutine " + coroutine.name + coroutine.desc); }/*from w w w. ja va 2 s . c o m*/ String coroutineName = getCoroutineName(coroutine); MethodTransformer methodTransformer = new MethodTransformer(coroutine, thisType); MethodNode coroutineImpl = methodTransformer.transform(coroutineName, generateDebugCode); thisNode.methods.add(coroutineImpl); /* * generate co iterators and method stubs */ log.finest("Generating CoIterator implementation and method stubs"); String baseCoIteratorName; Map<String, Object> annotation = getCoroutineAnnotationValues(coroutine); if (getBoolean(annotation, "threadLocal")) { baseCoIteratorName = Type.getInternalName(ThreadLocalCoIterator.class); } else { baseCoIteratorName = Type.getInternalName(SingleThreadedCoIterator.class); } String coIteratorClassName = "pl/clareo/coroutines/core/CoIterator" + num; ClassNode coIteratorClass = new ClassNode(); coIteratorClass.version = Opcodes.V1_6; coIteratorClass.access = Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL | Opcodes.ACC_SUPER; coIteratorClass.name = coIteratorClassName; coIteratorClass.superName = baseCoIteratorName; if (generateDebugCode) { /* * If debugging code is emitted create field keeping JDK logger */ FieldNode loggerField = new FieldNode(Opcodes.ACC_PRIVATE | Opcodes.ACC_FINAL | Opcodes.ACC_STATIC, "logger", "Ljava/util/logging/Logger;", null, null); coIteratorClass.fields.add(loggerField); MethodNode clinit = new MethodNode(); clinit.access = Opcodes.ACC_STATIC; clinit.name = "<clinit>"; clinit.desc = "()V"; clinit.exceptions = Collections.EMPTY_LIST; String loggerName = thisType.getClassName(); InsnList clinitCode = clinit.instructions; clinitCode.add(new LdcInsnNode(loggerName)); clinitCode.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "java/util/logging/Logger", "getLogger", "(Ljava/lang/String;)Ljava/util/logging/Logger;")); clinitCode.add(new FieldInsnNode(Opcodes.PUTSTATIC, coIteratorClassName, "logger", "Ljava/util/logging/Logger;")); clinitCode.add(new InsnNode(Opcodes.RETURN)); clinit.maxStack = 1; clinit.maxLocals = 0; coIteratorClass.methods.add(clinit); } /* * Generate constructor */ MethodNode init = new MethodNode(); init.access = Opcodes.ACC_PUBLIC; init.name = "<init>"; init.desc = CO_ITERATOR_CONSTRUCTOR_DESCRIPTOR; init.exceptions = Collections.EMPTY_LIST; InsnList initCode = init.instructions; initCode.add(new VarInsnNode(Opcodes.ALOAD, 0)); initCode.add(new VarInsnNode(Opcodes.ALOAD, 1)); initCode.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, baseCoIteratorName, "<init>", CO_ITERATOR_CONSTRUCTOR_DESCRIPTOR)); initCode.add(new InsnNode(Opcodes.RETURN)); init.maxStack = 2; init.maxLocals = 2; coIteratorClass.methods.add(init); /* * Generate overriden call to coroutine */ MethodNode call = new MethodNode(); call.access = Opcodes.ACC_PROTECTED; call.name = "call"; call.desc = CALL_METHOD_DESCRIPTOR; call.exceptions = Collections.EMPTY_LIST; InsnList callCode = call.instructions; /* * if debug needed generate call details */ if (generateDebugCode) { String coroutineId = "Coroutine " + coroutine.name; callCode.add(loggingInstructions(coIteratorClassName, "logger", Level.FINER, coroutineId + " call. Caller sent: ", 2)); callCode.add(new FrameNode(Opcodes.F_SAME, 0, EMPTY_LOCALS, 0, EMPTY_STACK)); callCode.add(loggingInstructions(coIteratorClassName, "logger", Level.FINEST, coroutineId + " state ", 1)); callCode.add(new FrameNode(Opcodes.F_SAME, 0, EMPTY_LOCALS, 0, EMPTY_STACK)); } /* * push call arguments: this (if not static), frame, input, output */ boolean isStatic = (coroutine.access & Opcodes.ACC_STATIC) != 0; if (!isStatic) { callCode.add(new VarInsnNode(Opcodes.ALOAD, 1)); callCode.add( new MethodInsnNode(Opcodes.INVOKEVIRTUAL, FRAME_NAME, "getThis", "()Ljava/lang/Object;")); callCode.add(new TypeInsnNode(Opcodes.CHECKCAST, thisType.getInternalName())); } callCode.add(new VarInsnNode(Opcodes.ALOAD, 1)); callCode.add(new InsnNode(Opcodes.ACONST_NULL)); callCode.add(new VarInsnNode(Opcodes.ALOAD, 2)); callCode.add(new MethodInsnNode(isStatic ? Opcodes.INVOKESTATIC : Opcodes.INVOKEVIRTUAL, thisType.getInternalName(), coroutineName, COROUTINE_METHOD_DESCRIPTOR)); // stack: * if (!generateDebugCode) { callCode.add(new InsnNode(Opcodes.ARETURN)); } else { // save result display suspension point (two more locals // needed) callCode.add(new VarInsnNode(Opcodes.ASTORE, 3)); callCode.add(new VarInsnNode(Opcodes.ALOAD, 1)); callCode.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, FRAME_NAME, "getLineOfCode", "()I")); callCode.add(box_int(Type.INT)); callCode.add(new VarInsnNode(Opcodes.ASTORE, 4)); callCode.add(loggingInstructions(coIteratorClassName, "logger", Level.FINER, "Coroutine suspended at line ", 4, ". Yielded:", 3)); callCode.add(new FrameNode(Opcodes.F_APPEND, 2, new Object[] { "java/lang/Object", "java/lang/Integer" }, 0, EMPTY_STACK)); callCode.add(new VarInsnNode(Opcodes.ALOAD, 3)); callCode.add(new InsnNode(Opcodes.ARETURN)); } coIteratorClass.methods.add(call); // if debugging code is emitted it needs space for two // additional locals and 5 stack operand if (generateDebugCode) { call.maxStack = 5; call.maxLocals = 5; } else { if (isStatic) { call.maxStack = 3; } else { call.maxStack = 4; } call.maxLocals = 3; } /* * CoIterator created - define it in the runtime and verify if * needed */ if (log.isLoggable(Level.FINEST)) { log.finest("Generated class " + coIteratorClassName); } ClassWriter cw = new ClassWriter(0); coIteratorClass.accept(cw); byte[] classBytes = cw.toByteArray(); try { CoroutineInstrumentator.dumpClass(coIteratorClassName, classBytes); } catch (IOException e) { throw new CoroutineGenerationException("Unable to write class " + coIteratorClassName, e); } /* * start generating method - new method is named as the method in * user code, it: returns instance of appropriate CoIterator (see * above), saves arguments of call */ if (log.isLoggable(Level.FINEST)) { log.finest("Instrumenting method " + coroutine.name); } InsnList code = coroutine.instructions; code.clear(); /* * create new Frame */ boolean isDebugFramePossible = generateDebugCode && coroutine.localVariables != null; if (isDebugFramePossible) { code.add(createDebugFrame(coroutine)); } else { code.add(createFrame(coroutine)); } /* * save frame in the first, and locals array in the second local * variable */ int argsSize = Type.getArgumentsAndReturnSizes(coroutine.desc) >> 2; if (isStatic) { argsSize -= 1; } code.add(new VarInsnNode(Opcodes.ASTORE, argsSize)); code.add(new VarInsnNode(Opcodes.ALOAD, argsSize)); code.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, FRAME_NAME, "getLocals", "()[Ljava/lang/Object;")); int localsArrayIndex = argsSize + 1; code.add(new VarInsnNode(Opcodes.ASTORE, localsArrayIndex)); /* * save all call arguments (along with this if this method is not * static) into locals array */ Type[] argsTypes = Type.getArgumentTypes(coroutine.desc); if (!isStatic) { code.add(saveloc(localsArrayIndex, 0, 0, JAVA_LANG_OBJECT)); code.add(savelocs(localsArrayIndex, 1, 1, argsTypes)); } else { code.add(savelocs(localsArrayIndex, 0, 0, argsTypes)); } /* * create CoIterator instance with saved frame, make initial call to * next if needed and return to caller */ code.add(new TypeInsnNode(Opcodes.NEW, coIteratorClassName)); code.add(new InsnNode(Opcodes.DUP)); code.add(new VarInsnNode(Opcodes.ALOAD, argsSize)); code.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, coIteratorClassName, "<init>", CO_ITERATOR_CONSTRUCTOR_DESCRIPTOR)); if (!getBoolean(annotation, "generator", true)) { code.add(new InsnNode(Opcodes.DUP)); code.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, coIteratorClassName, "next", "()Ljava/lang/Object;")); code.add(new InsnNode(Opcodes.POP)); } code.add(new InsnNode(Opcodes.ARETURN)); /* * end method generation; maxs can be statically determined 3 * operands on stack (call to frame setLocals and CoIterator * constructor) + 1 if any argument is long or double (debug frame * needs 7 operands for variable names creation); locals = argsSize * + 1 reference to frame + 1 array of locals */ if (isDebugFramePossible) { coroutine.maxStack = 7; } else { boolean isCategory2ArgumentPresent = false; for (Type argType : argsTypes) { int sort = argType.getSort(); if (sort == Type.LONG || sort == Type.DOUBLE) { isCategory2ArgumentPresent = true; break; } } coroutine.maxStack = isCategory2ArgumentPresent ? 4 : 3; } coroutine.maxLocals = localsArrayIndex + 1; coroutine.localVariables.clear(); coroutine.tryCatchBlocks.clear(); num++; } }
From source file:portablejim.veinminer.asm.ItemInWorldManagerTransformer.java
License:Open Source License
private InsnList buildBlockIdFunctionCall(String obfuscatedClassName, String worldType, int blockVarIndex) { InsnList blockIdFunctionCall = new InsnList(); blockIdFunctionCall.add(new TypeInsnNode(Opcodes.NEW, blockIdClassName)); blockIdFunctionCall.add(new InsnNode(Opcodes.DUP)); blockIdFunctionCall.add(new VarInsnNode(Opcodes.ALOAD, 0)); blockIdFunctionCall.add(new FieldInsnNode(Opcodes.GETFIELD, obfuscatedClassName.replace(".", "/"), getCorrectName("theWorld"), typemap.get(getCorrectName("theWorld")))); blockIdFunctionCall.add(new VarInsnNode(Opcodes.ILOAD, 1)); blockIdFunctionCall.add(new VarInsnNode(Opcodes.ILOAD, 2)); blockIdFunctionCall.add(new VarInsnNode(Opcodes.ILOAD, 3)); blockIdFunctionCall.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, blockIdClassName, "<init>", String.format("(%sIII)V", worldType))); blockIdFunctionCall.add(new VarInsnNode(Opcodes.ASTORE, blockVarIndex)); return blockIdFunctionCall; }
From source file:pt.minha.kernel.instrument.SyncToMonitorClassVisitor.java
License:Open Source License
public void makeStub(int access, String name, String desc, String signature, String[] exceptions) { Method m = new Method(name, desc); MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions); mv.visitCode();//from w w w. j a va 2s . c o m Label begin = new Label(); Label pre_invoke = new Label(); Label pos_leave = new Label(); Label in_catch = new Label(); Label pre_rethrow = new Label(); Label end = new Label(); mv.visitTryCatchBlock(pre_invoke, pos_leave, in_catch, null); mv.visitTryCatchBlock(in_catch, pre_rethrow, in_catch, null); mv.visitLabel(begin); int offset; if ((access & Opcodes.ACC_STATIC) == 0) { mv.visitVarInsn(Opcodes.ALOAD, 0); offset = 1; } else { mv.visitFieldInsn(Opcodes.GETSTATIC, clz, "_fake_class", "L" + ClassConfig.fake_prefix + "java/lang/Object;"); offset = 0; } int length = 0; for (Type t : m.getArgumentTypes()) length += t.getSize(); mv.visitInsn(Opcodes.DUP); mv.visitVarInsn(Opcodes.ASTORE, offset + length); mv.visitInsn(Opcodes.MONITORENTER); mv.visitLabel(pre_invoke); if ((access & Opcodes.ACC_STATIC) == 0) mv.visitVarInsn(Opcodes.ALOAD, 0); int i = offset; for (Type t : m.getArgumentTypes()) { // t.getOpcode() should work for long and double too... :-( if (t.getClassName().equals("long")) mv.visitVarInsn(Opcodes.LLOAD, i); else if (t.getClassName().equals("double")) mv.visitVarInsn(Opcodes.DLOAD, i); else mv.visitVarInsn(t.getOpcode(Opcodes.ILOAD), i); i += t.getSize(); } boolean itf = (access & Opcodes.ACC_INTERFACE) != 0; if ((access & Opcodes.ACC_STATIC) == 0) mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, clz, "_" + name, desc, itf); else mv.visitMethodInsn(Opcodes.INVOKESTATIC, clz, "_" + name, desc, itf); mv.visitVarInsn(Opcodes.ALOAD, offset + length); mv.visitInsn(Opcodes.MONITOREXIT); mv.visitLabel(pos_leave); if (m.getReturnType().equals(Type.VOID_TYPE)) mv.visitInsn(Opcodes.RETURN); else mv.visitInsn(m.getReturnType().getOpcode(Opcodes.IRETURN)); mv.visitLabel(in_catch); mv.visitVarInsn(Opcodes.ALOAD, offset + length); mv.visitInsn(Opcodes.MONITOREXIT); mv.visitLabel(pre_rethrow); mv.visitInsn(Opcodes.ATHROW); mv.visitLabel(end); i = 0; if ((access & Opcodes.ACC_STATIC) == 0) mv.visitLocalVariable("this", "L" + clz + ";", null, begin, end, i++); for (Type t : m.getArgumentTypes()) mv.visitLocalVariable("arg" + i, t.getDescriptor(), null, begin, end, i++); mv.visitMaxs(0, 0); mv.visitEnd(); }
From source file:scouter.agent.asm.asyncsupport.CallRunnableASM.java
License:Apache License
private void capReturn() { Type tp = returnType;//from w w w. ja v a2 s . c om if (tp == null || tp.equals(Type.VOID_TYPE)) { mv.visitInsn(Opcodes.ACONST_NULL); mv.visitVarInsn(Opcodes.ALOAD, statIdx); mv.visitInsn(Opcodes.ACONST_NULL); mv.visitMethodInsn(Opcodes.INVOKESTATIC, TARGET, END_METHOD, END_METHOD_DESC, false); return; } switch (tp.getSort()) { case Type.DOUBLE: case Type.LONG: mv.visitInsn(Opcodes.DUP2); break; default: mv.visitInsn(Opcodes.DUP); } // TODO method return test dup and store // int rtnIdx = newLocal(tp); // mv.visitVarInsn(Opcodes.ASTORE, rtnIdx); // mv.visitVarInsn(Opcodes.ALOAD, rtnIdx); mv.visitVarInsn(Opcodes.ALOAD, statIdx);// stat mv.visitInsn(Opcodes.ACONST_NULL);// throwable mv.visitMethodInsn(Opcodes.INVOKESTATIC, TARGET, END_METHOD, END_METHOD_DESC, false); }
From source file:scouter.agent.asm.redis.RedisCacheKeyASM.java
License:Apache License
public void visitInsn(int opcode) { if ((opcode >= IRETURN && opcode <= RETURN)) { Type tp = returnType;/* www .j a v a2 s.co m*/ if (tp.getSort() == Type.ARRAY && tp.getElementType().getSort() == Type.BYTE) { mv.visitInsn(Opcodes.DUP); mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn(GETFIELD, this.className, KEY_ELEMENT_FIELD, "Ljava/lang/Object;"); mv.visitMethodInsn(Opcodes.INVOKESTATIC, TRACEMAIN, START_METHOD, START_SIGNATURE, false); } } mv.visitInsn(opcode); }
From source file:scouter.agent.asm.redis.RedisKeyASM.java
License:Apache License
public void visitInsn(int opcode) { if ((opcode >= IRETURN && opcode <= RETURN)) { Type tp = returnType;// w w w.jav a 2 s .c om if (tp.getSort() == Type.ARRAY && tp.getElementType().getSort() == Type.BYTE) { mv.visitInsn(Opcodes.DUP); mv.visitVarInsn(Opcodes.ALOAD, 1);// stat mv.visitMethodInsn(Opcodes.INVOKESTATIC, TRACEMAIN, START_METHOD, START_SIGNATURE, false); } } mv.visitInsn(opcode); }
From source file:serianalyzer.JVMImpl.java
License:Open Source License
/** * @param opcode//w ww . jav a2s.c o m * @param s */ static void handleJVMInsn(int opcode, JVMStackState s) { BaseType o1; BaseType o2; BaseType o3; List<BaseType> l1; List<BaseType> l2; switch (opcode) { case Opcodes.NOP: break; case Opcodes.ARRAYLENGTH: o1 = s.pop(); s.push(new BasicConstant(Type.INT_TYPE, 0, !(o1 != null && !o1.isTainted()))); break; case Opcodes.ACONST_NULL: s.push(new BasicConstant(Type.VOID_TYPE, "<null>")); //$NON-NLS-1$ break; case Opcodes.ICONST_M1: case Opcodes.ICONST_0: case Opcodes.ICONST_1: case Opcodes.ICONST_2: case Opcodes.ICONST_3: case Opcodes.ICONST_4: case Opcodes.ICONST_5: s.push(new BasicConstant(Type.INT_TYPE, opcode - 3)); break; case Opcodes.LCONST_0: case Opcodes.LCONST_1: s.push(new BasicConstant(Type.LONG_TYPE, opcode - 9L)); break; case Opcodes.FCONST_0: case Opcodes.FCONST_1: case Opcodes.FCONST_2: s.push(new BasicConstant(Type.FLOAT_TYPE, opcode - 11f)); break; case Opcodes.DCONST_0: case Opcodes.DCONST_1: s.push(new BasicConstant(Type.DOUBLE_TYPE, opcode - 14d)); break; case Opcodes.IALOAD: case Opcodes.LALOAD: case Opcodes.FALOAD: case Opcodes.DALOAD: case Opcodes.BALOAD: case Opcodes.CALOAD: case Opcodes.SALOAD: o1 = s.pop(); o2 = s.pop(); s.push(new BasicVariable(toType(opcode), "primitive array elem", //$NON-NLS-1$ (o1 == null || o1.isTainted()) | (o2 == null || o2.isTainted()))); break; case Opcodes.AALOAD: o1 = s.pop(); o2 = s.pop(); if (o1 != null && o2 instanceof SimpleType && ((SimpleType) o2).getType().toString().startsWith("[")) { //$NON-NLS-1$ Type atype = Type.getType(((SimpleType) o2).getType().toString().substring(1)); if (o2.getAlternativeTypes() != null && !o2.getAlternativeTypes().isEmpty()) { s.clear(); break; } s.push(new BasicVariable(atype, "array elem " + atype, o1.isTainted() | o2.isTainted())); //$NON-NLS-1$ } else { s.clear(); } break; case Opcodes.IASTORE: case Opcodes.LASTORE: case Opcodes.FASTORE: case Opcodes.DASTORE: case Opcodes.AASTORE: case Opcodes.BASTORE: case Opcodes.CASTORE: case Opcodes.SASTORE: s.pop(3); break; case Opcodes.POP2: s.pop(); case Opcodes.MONITORENTER: case Opcodes.MONITOREXIT: case Opcodes.POP: s.pop(); break; case Opcodes.DUP: if (!s.isEmpty()) { o1 = s.pop(); s.push(o1); s.push(o1); } break; case Opcodes.DUP_X1: o1 = s.pop(); o2 = s.pop(); s.push(o1); s.push(o2); s.push(o1); break; case Opcodes.DUP_X2: o1 = s.pop(); o2 = s.pop(); o3 = s.pop(); s.push(o1); s.push(o3); s.push(o2); s.push(o1); break; case Opcodes.DUP2: l1 = s.popWord(); if (l1.isEmpty()) { log.trace("DUP2 with unknown operand"); //$NON-NLS-1$ s.clear(); } else { s.pushWord(l1); s.pushWord(l1); } break; case Opcodes.DUP2_X1: l1 = s.popWord(); o1 = s.pop(); if (l1.isEmpty()) { log.trace("DUP2 with unknown operand"); //$NON-NLS-1$ s.clear(); } else { s.pushWord(l1); s.push(o1); s.pushWord(l1); } break; case Opcodes.DUP2_X2: l1 = s.popWord(); l2 = s.popWord(); if (l1.isEmpty() || l2.isEmpty()) { log.trace("DUP2 with unknown operand"); //$NON-NLS-1$ s.clear(); } else { s.pushWord(l1); s.pushWord(l2); s.pushWord(l1); } break; case Opcodes.SWAP: o1 = s.pop(); o2 = s.pop(); s.push(o1); s.push(o2); break; case Opcodes.IADD: case Opcodes.LADD: case Opcodes.FADD: case Opcodes.DADD: case Opcodes.ISUB: case Opcodes.LSUB: case Opcodes.FSUB: case Opcodes.DSUB: case Opcodes.IMUL: case Opcodes.LMUL: case Opcodes.FMUL: case Opcodes.DMUL: case Opcodes.IDIV: case Opcodes.LDIV: case Opcodes.FDIV: case Opcodes.DDIV: case Opcodes.IREM: case Opcodes.LREM: case Opcodes.FREM: case Opcodes.DREM: case Opcodes.IAND: case Opcodes.LAND: case Opcodes.IOR: case Opcodes.LOR: case Opcodes.IXOR: case Opcodes.LXOR: case Opcodes.LCMP: case Opcodes.FCMPL: case Opcodes.FCMPG: case Opcodes.DCMPL: case Opcodes.DCMPG: s.merge(2); break; case Opcodes.ISHL: case Opcodes.LSHL: case Opcodes.ISHR: case Opcodes.LSHR: case Opcodes.IUSHR: case Opcodes.LUSHR: s.pop(); // amount // ignore value break; case Opcodes.INEG: case Opcodes.F2I: case Opcodes.D2I: case Opcodes.L2I: s.push(cast(s.pop(), Type.INT_TYPE)); break; case Opcodes.LNEG: case Opcodes.I2L: case Opcodes.F2L: case Opcodes.D2L: s.push(cast(s.pop(), Type.LONG_TYPE)); break; case Opcodes.FNEG: case Opcodes.I2F: case Opcodes.L2F: case Opcodes.D2F: s.push(cast(s.pop(), Type.FLOAT_TYPE)); case Opcodes.DNEG: case Opcodes.I2D: case Opcodes.L2D: case Opcodes.F2D: s.push(cast(s.pop(), Type.DOUBLE_TYPE)); case Opcodes.I2B: s.push(cast(s.pop(), Type.BYTE_TYPE)); break; case Opcodes.I2C: s.push(cast(s.pop(), Type.CHAR_TYPE)); break; case Opcodes.I2S: s.push(cast(s.pop(), Type.SHORT_TYPE)); break; case Opcodes.ARETURN: s.clear(); break; case Opcodes.IRETURN: case Opcodes.LRETURN: case Opcodes.FRETURN: case Opcodes.DRETURN: case Opcodes.RETURN: if (log.isTraceEnabled()) { log.trace("Found return " + s.pop()); //$NON-NLS-1$ } s.clear(); break; case Opcodes.ATHROW: Object thrw = s.pop(); log.trace("Found throw " + thrw); //$NON-NLS-1$ s.clear(); break; default: log.warn("Unsupported instruction code " + opcode); //$NON-NLS-1$ } }
From source file:sg.atom.core.actor.internal.codegenerator.ActorProxyCreator.java
License:Apache License
/** * Creates and loads the actor's proxy class. * * @param actorClass the Actor class//from ww w . j av a 2 s .com * @param acd the actor's class descriptor * @throws ConfigurationException if the agent is not configured correctly */ @SuppressWarnings("unchecked") private static Class<?> generateProxyClass(Class<?> actorClass, final ActorClassDescriptor acd) throws NoSuchMethodException { BeanClassDescriptor bcd = acd.getBeanClassDescriptor(); String className = String.format("%s__ACTORPROXY", actorClass.getName()); final String classNameInternal = className.replace('.', '/'); String classNameDescriptor = "L" + classNameInternal + ";"; final Type actorState = Type .getType(acd.getConcurrencyModel().isMultiThreadingCapable() ? MultiThreadedActorState.class : SingleThreadedActorState.class); ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES); MethodVisitor mv; cw.visit(codeVersion, Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL + Opcodes.ACC_SUPER + Opcodes.ACC_SYNTHETIC, classNameInternal, null, Type.getInternalName(actorClass), new String[] { "org/actorsguildframework/internal/ActorProxy" }); cw.visitSource(null, null); { for (int i = 0; i < acd.getMessageCount(); i++) { cw.visitField(Opcodes.ACC_PRIVATE + Opcodes.ACC_FINAL + Opcodes.ACC_STATIC, String.format(MESSAGE_CALLER_NAME_FORMAT, i), "Lorg/actorsguildframework/internal/MessageCaller;", "Lorg/actorsguildframework/internal/MessageCaller<*>;", null).visitEnd(); } cw.visitField(Opcodes.ACC_PRIVATE + Opcodes.ACC_FINAL, "actorState__ACTORPROXY", actorState.getDescriptor(), null, null).visitEnd(); } BeanCreator.writePropFields(bcd, cw); { mv = cw.visitMethod(Opcodes.ACC_STATIC, "<clinit>", "()V", null, null); mv.visitCode(); for (int i = 0; i < acd.getMessageCount(); i++) { Class<?> caller = createMessageCaller(acd.getMessage(i).getOwnerClass(), acd.getMessage(i).getMethod()); String mcName = Type.getInternalName(caller); mv.visitTypeInsn(Opcodes.NEW, mcName); mv.visitInsn(Opcodes.DUP); mv.visitMethodInsn(Opcodes.INVOKESPECIAL, mcName, "<init>", "()V"); mv.visitFieldInsn(Opcodes.PUTSTATIC, classNameInternal, String.format(MESSAGE_CALLER_NAME_FORMAT, i), "Lorg/actorsguildframework/internal/MessageCaller;"); } mv.visitInsn(Opcodes.RETURN); mv.visitMaxs(0, 0); mv.visitEnd(); } BeanCreator.writeConstructor(actorClass, bcd, classNameInternal, cw, new BeanCreator.SnippetWriter() { @Override public void write(MethodVisitor mv) { mv.visitVarInsn(Opcodes.ALOAD, 0); mv.visitTypeInsn(Opcodes.NEW, actorState.getInternalName()); mv.visitInsn(Opcodes.DUP); mv.visitVarInsn(Opcodes.ALOAD, 1); mv.visitVarInsn(Opcodes.ALOAD, 0); mv.visitMethodInsn(Opcodes.INVOKESPECIAL, actorState.getInternalName(), "<init>", "(Lorg/actorsguildframework/internal/Controller;Lorg/actorsguildframework/Actor;)V"); mv.visitFieldInsn(Opcodes.PUTFIELD, classNameInternal, "actorState__ACTORPROXY", actorState.getDescriptor()); } }); BeanCreator.writePropAccessors(bcd, classNameInternal, cw); { mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "getState__ACTORPROXYMETHOD", "()Lorg/actorsguildframework/internal/ActorState;", null, null); mv.visitCode(); Label l0 = new Label(); mv.visitLabel(l0); mv.visitVarInsn(Opcodes.ALOAD, 0); mv.visitFieldInsn(Opcodes.GETFIELD, classNameInternal, "actorState__ACTORPROXY", actorState.getDescriptor()); mv.visitInsn(Opcodes.ARETURN); Label l1 = new Label(); mv.visitLabel(l1); mv.visitLocalVariable("this", classNameDescriptor, null, l0, l1, 0); mv.visitMaxs(0, 0); mv.visitEnd(); } for (int i = 0; i < acd.getMessageCount(); i++) { MessageImplDescriptor mid = acd.getMessage(i); Method method = mid.getMethod(); String simpleDescriptor = Type.getMethodDescriptor(method); String genericSignature = GenericTypeHelper.getSignature(method); writeProxyMethod(classNameInternal, classNameDescriptor, cw, i, actorState, acd.getConcurrencyModel(), mid, method, simpleDescriptor, genericSignature); writeSuperProxyMethod(actorClass, classNameDescriptor, cw, method, simpleDescriptor, genericSignature, !acd.getConcurrencyModel().isMultiThreadingCapable()); } { mv = cw.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_SYNCHRONIZED, "toString", "()Ljava/lang/String;", null, null); mv.visitCode(); Label l0 = new Label(); mv.visitLabel(l0); mv.visitVarInsn(Opcodes.ALOAD, 0); mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "toString", "()Ljava/lang/String;"); mv.visitInsn(Opcodes.ARETURN); Label l1 = new Label(); mv.visitLabel(l1); mv.visitLocalVariable("this", classNameDescriptor, null, l0, l1, 0); mv.visitMaxs(0, 0); mv.visitEnd(); } cw.visitEnd(); try { return (Class<? extends ActorProxy>) GenerationUtils.loadClass(className, cw.toByteArray()); } catch (Exception e) { throw new ConfigurationException("Failure loading ActorProxy", e); } }
From source file:sg.atom.core.actor.internal.codegenerator.ActorProxyCreator.java
License:Apache License
/** * Writes a proxy method for messages./*from w ww .ja v a2 s . c o m*/ * * @param classNameInternal the internal class name * @param classNameDescriptor the class name descriptor * @param cw the ClassWriter * @param index the message index * @param type the ActorState type to use * @param concurrencyModel the concurrency model of the message * @param messageDescriptor the message's descriptor * @param method the method to override * @param simpleDescriptor a simple descriptor of the message * @param genericSignature the signature of the message */ private static void writeProxyMethod(String classNameInternal, String classNameDescriptor, ClassWriter cw, int index, Type actorState, ConcurrencyModel concurrencyModel, MessageImplDescriptor messageDescriptor, Method method, String simpleDescriptor, String genericSignature) throws NoSuchMethodException { MethodVisitor mv; { mv = cw.visitMethod(Opcodes.ACC_PUBLIC, method.getName(), simpleDescriptor, genericSignature, null); mv.visitCode(); Label l0 = new Label(); mv.visitLabel(l0); mv.visitIntInsn(Opcodes.BIPUSH, method.getParameterTypes().length); mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object"); for (int j = 0; j < method.getParameterTypes().length; j++) { mv.visitInsn(Opcodes.DUP); mv.visitIntInsn(Opcodes.BIPUSH, j); Class<?> paraType = method.getParameterTypes()[j]; if (paraType.isPrimitive()) { String wrapperClass = GenerationUtils.getWrapperInternalName(paraType); Type primType = Type.getType(paraType); mv.visitVarInsn(primType.getOpcode(Opcodes.ILOAD), j + 1); mv.visitMethodInsn(Opcodes.INVOKESTATIC, wrapperClass, "valueOf", "(" + primType.getDescriptor() + ")" + "L" + wrapperClass + ";"); } else if (isArgumentFreezingRequired(method, j, paraType)) { mv.visitVarInsn(Opcodes.ALOAD, j + 1); mv.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(SerializableFreezer.class), "freeze", Type.getMethodDescriptor(SerializableFreezer.class.getMethod("freeze", Object.class))); } else if (paraType.isInterface()) { mv.visitVarInsn(Opcodes.ALOAD, j + 1); mv.visitInsn(Opcodes.DUP); mv.visitTypeInsn(Opcodes.INSTANCEOF, "org/actorsguildframework/Actor"); Label lEndif = new Label(); mv.visitJumpInsn(Opcodes.IFNE, lEndif); mv.visitTypeInsn(Opcodes.NEW, Type.getInternalName(ActorRuntimeException.class)); mv.visitInsn(Opcodes.DUP); mv.visitLdcInsn(String.format( "Argument %d is an non-Serializable interface, but you did not give an Actor. If a message's argument type is an interface that does not extend Serializable, only Actors are acceptable as argument.", j)); mv.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(ActorRuntimeException.class), "<init>", "(Ljava/lang/String;)V"); mv.visitInsn(Opcodes.ATHROW); mv.visitLabel(lEndif); } else { mv.visitVarInsn(Opcodes.ALOAD, j + 1); } mv.visitInsn(Opcodes.AASTORE); } Label l1 = new Label(); mv.visitLabel(l1); mv.visitVarInsn(Opcodes.ASTORE, method.getParameterTypes().length + 1); // method.getParameterTypes().length+1 ==> 'args' local variable mv.visitVarInsn(Opcodes.ALOAD, 0); mv.visitFieldInsn(Opcodes.GETFIELD, classNameInternal, "actorState__ACTORPROXY", actorState.getDescriptor()); mv.visitFieldInsn(Opcodes.GETSTATIC, classNameInternal, String.format(MESSAGE_CALLER_NAME_FORMAT, index), "Lorg/actorsguildframework/internal/MessageCaller;"); mv.visitFieldInsn(Opcodes.GETSTATIC, "org/actorsguildframework/annotations/ThreadUsage", messageDescriptor.getThreadUsage().name(), "Lorg/actorsguildframework/annotations/ThreadUsage;"); mv.visitVarInsn(Opcodes.ALOAD, method.getParameterTypes().length + 1); mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, actorState.getInternalName(), "queueMessage", "(Lorg/actorsguildframework/internal/MessageCaller;Lorg/actorsguildframework/annotations/ThreadUsage;[Ljava/lang/Object;)Lorg/actorsguildframework/internal/AsyncResultImpl;"); mv.visitInsn(Opcodes.ARETURN); Label l4 = new Label(); mv.visitLabel(l4); mv.visitLocalVariable("this", classNameDescriptor, null, l0, l4, 0); for (int j = 0; j < method.getParameterTypes().length; j++) { mv.visitLocalVariable("arg" + j, Type.getDescriptor(method.getParameterTypes()[j]), GenericTypeHelper.getSignatureIfGeneric(method.getGenericParameterTypes()[j]), l0, l4, j + 1); } mv.visitLocalVariable("args", "[Ljava/lang/Object;", null, l1, l4, method.getParameterTypes().length + 1); mv.visitMaxs(0, 0); mv.visitEnd(); } }
From source file:sg.atom.core.actor.internal.codegenerator.BeanCreator.java
License:Apache License
/** * Writes the bean constructor to the given ClassWriter. * * @param beanClass the original bean class to extend * @param bcd the descriptor of the bean * @param classNameInternal the internal name of the new class * @param cw the ClassWriter to write to * @param snippetWriter if not null, this will be invoked to add a snippet * after the invocation of the super constructor *///from ww w . jav a 2 s .co m public static void writeConstructor(Class<?> beanClass, BeanClassDescriptor bcd, String classNameInternal, ClassWriter cw, SnippetWriter snippetWriter) { String classNameDescriptor = "L" + classNameInternal + ";"; int localPropertySize = 0; ArrayList<PropertyDescriptor> localVarProperties = new ArrayList<PropertyDescriptor>(); for (int i = 0; i < bcd.getPropertyCount(); i++) { PropertyDescriptor pd = bcd.getProperty(i); if (pd.getPropertySource().isGenerating() || (pd.getDefaultValue() != null)) { localVarProperties.add(pd); localPropertySize += Type.getType(pd.getPropertyClass()).getSize(); } } final int locVarThis = 0; final int locVarController = 1; final int locVarProps = 2; final int locVarPropertiesOffset = 3; final int locVarP = 3 + localPropertySize; final int locVarK = 4 + localPropertySize; final int locVarV = 5 + localPropertySize; MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "(Lorg/actorsguildframework/internal/Controller;Lorg/actorsguildframework/Props;)V", null, null); mv.visitCode(); Label lTry = new Label(); Label lCatch = new Label(); mv.visitTryCatchBlock(lTry, lCatch, lCatch, "java/lang/ClassCastException"); Label lBegin = new Label(); mv.visitLabel(lBegin); mv.visitVarInsn(Opcodes.ALOAD, locVarThis); mv.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(beanClass), "<init>", "()V"); if (snippetWriter != null) { snippetWriter.write(mv); } Label lPropertyInit = new Label(); mv.visitLabel(lPropertyInit); // load default values into the local variables for each property that must be set int varCount = 0; for (PropertyDescriptor pd : localVarProperties) { Type pt = Type.getType(pd.getPropertyClass()); if (pd.getDefaultValue() != null) { mv.visitFieldInsn(Opcodes.GETSTATIC, Type.getInternalName(pd.getDefaultValue().getDeclaringClass()), pd.getDefaultValue().getName(), Type.getDescriptor(pd.getDefaultValue().getType())); } else { GenerationUtils.generateLoadDefault(mv, pd.getPropertyClass()); } mv.visitVarInsn(pt.getOpcode(Opcodes.ISTORE), locVarPropertiesOffset + varCount); varCount += pt.getSize(); } // loop through the props argument's list mv.visitVarInsn(Opcodes.ALOAD, locVarProps); mv.visitVarInsn(Opcodes.ASTORE, locVarP); Label lWhile = new Label(); Label lEndWhile = new Label(); Label lWhileBody = new Label(); mv.visitLabel(lWhile); mv.visitJumpInsn(Opcodes.GOTO, lEndWhile); mv.visitLabel(lWhileBody); mv.visitVarInsn(Opcodes.ALOAD, locVarP); mv.visitInsn(Opcodes.DUP); mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "org/actorsguildframework/Props", "getKey", "()Ljava/lang/String;"); mv.visitVarInsn(Opcodes.ASTORE, locVarK); mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "org/actorsguildframework/Props", "getValue", "()Ljava/lang/Object;"); mv.visitVarInsn(Opcodes.ASTORE, locVarV); mv.visitLabel(lTry); // write an if for each property Label lEndIf = new Label(); varCount = 0; int ifCount = 0; for (int i = 0; i < bcd.getPropertyCount(); i++) { PropertyDescriptor pd = bcd.getProperty(i); boolean usesLocal = pd.getPropertySource().isGenerating() || (pd.getDefaultValue() != null); Class<?> propClass = pd.getPropertyClass(); Type pt = Type.getType(propClass); mv.visitVarInsn(Opcodes.ALOAD, locVarK); mv.visitLdcInsn(pd.getName()); mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "equals", "(Ljava/lang/Object;)Z"); Label lElse = new Label(); mv.visitJumpInsn(Opcodes.IFEQ, lElse); if (!usesLocal) { mv.visitVarInsn(Opcodes.ALOAD, locVarThis); // for setter invocation, load 'this' } if (propClass.isPrimitive()) { mv.visitLdcInsn(pd.getName()); mv.visitVarInsn(Opcodes.ALOAD, locVarV); mv.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(BeanHelper.class), String.format("get%s%sFromPropValue", propClass.getName().substring(0, 1).toUpperCase(Locale.US), propClass.getName().substring(1)), "(Ljava/lang/String;Ljava/lang/Object;)" + pt.getDescriptor()); } else if (!propClass.equals(Object.class)) { mv.visitVarInsn(Opcodes.ALOAD, locVarV); mv.visitTypeInsn(Opcodes.CHECKCAST, pt.getInternalName()); } else { mv.visitVarInsn(Opcodes.ALOAD, locVarV); } if (!usesLocal) { mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, classNameInternal, pd.getSetter().getName(), Type.getMethodDescriptor(pd.getSetter())); } else { mv.visitVarInsn(pt.getOpcode(Opcodes.ISTORE), varCount + locVarPropertiesOffset); } mv.visitJumpInsn(Opcodes.GOTO, lEndIf); mv.visitLabel(lElse); ifCount++; if (usesLocal) { varCount += pt.getSize(); } } // else (==> if not prop matched) throw IllegalArgumentException mv.visitTypeInsn(Opcodes.NEW, Type.getInternalName(IllegalArgumentException.class)); mv.visitInsn(Opcodes.DUP); mv.visitLdcInsn("Unknown property \"%s\"."); mv.visitInsn(Opcodes.ICONST_1); mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object"); mv.visitInsn(Opcodes.DUP); mv.visitInsn(Opcodes.ICONST_0); mv.visitVarInsn(Opcodes.ALOAD, locVarK); mv.visitInsn(Opcodes.AASTORE); mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/String", "format", "(Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/String;"); mv.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(IllegalArgumentException.class), "<init>", "(Ljava/lang/String;)V"); mv.visitInsn(Opcodes.ATHROW); mv.visitLabel(lCatch); mv.visitInsn(Opcodes.POP); // pop the exception object (not needed) mv.visitTypeInsn(Opcodes.NEW, Type.getInternalName(IllegalArgumentException.class)); mv.visitInsn(Opcodes.DUP); mv.visitLdcInsn("Incompatible type for property \"%s\". Got %s."); mv.visitInsn(Opcodes.ICONST_2); mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object"); mv.visitInsn(Opcodes.DUP); mv.visitInsn(Opcodes.ICONST_0); mv.visitVarInsn(Opcodes.ALOAD, locVarK); mv.visitInsn(Opcodes.AASTORE); mv.visitInsn(Opcodes.DUP); mv.visitInsn(Opcodes.ICONST_1); mv.visitVarInsn(Opcodes.ALOAD, locVarV); mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Object", "getClass", "()Ljava/lang/Class;"); mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Class", "getName", "()Ljava/lang/String;"); mv.visitInsn(Opcodes.AASTORE); mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/String", "format", "(Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/String;"); mv.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(IllegalArgumentException.class), "<init>", "(Ljava/lang/String;)V"); mv.visitInsn(Opcodes.ATHROW); mv.visitLabel(lEndIf); mv.visitVarInsn(Opcodes.ALOAD, locVarP); mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "org/actorsguildframework/Props", "tail", "()Lorg/actorsguildframework/Props;"); mv.visitVarInsn(Opcodes.ASTORE, locVarP); mv.visitLabel(lEndWhile); mv.visitVarInsn(Opcodes.ALOAD, locVarP); mv.visitJumpInsn(Opcodes.IFNONNULL, lWhileBody); // write local variables back into properties varCount = 0; for (PropertyDescriptor pd : localVarProperties) { Type pt = Type.getType(pd.getPropertyClass()); mv.visitVarInsn(Opcodes.ALOAD, locVarThis); if (pd.getPropertySource() == PropertySource.ABSTRACT_METHOD) { mv.visitVarInsn(pt.getOpcode(Opcodes.ILOAD), locVarPropertiesOffset + varCount); mv.visitFieldInsn(Opcodes.PUTFIELD, classNameInternal, String.format(PROP_FIELD_NAME_TEMPLATE, pd.getName()), pt.getDescriptor()); } else if (pd.getPropertySource() == PropertySource.USER_WRITTEN) { mv.visitVarInsn(pt.getOpcode(Opcodes.ILOAD), locVarPropertiesOffset + varCount); mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, classNameInternal, pd.getSetter().getName(), Type.getMethodDescriptor(pd.getSetter())); } else { throw new RuntimeException("Internal error"); } varCount += pt.getSize(); } // if bean is thread-safe, publish all writes now if (bcd.isThreadSafe()) { mv.visitVarInsn(Opcodes.ALOAD, locVarThis); mv.visitInsn(Opcodes.DUP); mv.visitInsn(Opcodes.MONITORENTER); mv.visitInsn(Opcodes.MONITOREXIT); } mv.visitInsn(Opcodes.RETURN); Label lEnd = new Label(); mv.visitLabel(lEnd); mv.visitLocalVariable("this", classNameDescriptor, null, lBegin, lEnd, locVarThis); mv.visitLocalVariable("controller", "Lorg/actorsguildframework/internal/Controller;", null, lBegin, lEnd, locVarController); mv.visitLocalVariable("props", "Lorg/actorsguildframework/Props;", null, lBegin, lEnd, locVarProps); varCount = 0; for (PropertyDescriptor pd : localVarProperties) { Type pt = Type.getType(pd.getPropertyClass()); mv.visitLocalVariable("__" + pd.getName(), pt.getDescriptor(), GenericTypeHelper.getSignature(pd.getPropertyType()), lPropertyInit, lEnd, locVarPropertiesOffset + varCount); varCount += pt.getSize(); } mv.visitLocalVariable("p", "Lorg/actorsguildframework/Props;", null, lPropertyInit, lEnd, locVarP); mv.visitLocalVariable("k", "Ljava/lang/String;", null, lWhile, lEndWhile, locVarK); mv.visitLocalVariable("v", "Ljava/lang/Object;", null, lWhile, lEndWhile, locVarV); mv.visitMaxs(0, 0); mv.visitEnd(); }