/** * Transforms the init method to create the newly added join point member field. * * @param cp the ConstantPoolGen * @param cg the ClassGen * @param init the constructor for the class * @param method the current method * @param factory the objectfactory * @param methodSequence the methods sequence number * @return the modified constructor */ private MethodGen createJoinPointField( final ConstantPoolGen cp, final ClassGen cg, final Method init, final Method method, final InstructionFactory factory, final int methodSequence) { final MethodGen mg = new MethodGen(init, cg.getClassName(), cp); final InstructionList il = mg.getInstructionList(); final InstructionHandle[] ihs = il.getInstructionHandles(); // grab the handle to the the return instruction of the constructor InstructionHandle ih = ihs[0]; for (int i = 0; i < ihs.length; i++) { Instruction instruction = ihs[i].getInstruction(); if (instruction instanceof ReturnInstruction) { ih = ihs[i]; // set the instruction handle to the return instruction break; } } final String joinPoint = getJoinPointName(method, methodSequence); final InstructionHandle ihPost; ihPost = il.insert(ih, factory.createLoad(Type.OBJECT, 0)); il.insert(ih, factory.createNew(TransformationUtil.THREAD_LOCAL_CLASS)); il.insert(ih, InstructionConstants.DUP); il.insert( ih, factory.createInvoke( TransformationUtil.THREAD_LOCAL_CLASS, "<init>", Type.VOID, new Type[] {}, Constants.INVOKESPECIAL)); il.insert( ih, factory.createFieldAccess( cg.getClassName(), joinPoint, new ObjectType(TransformationUtil.THREAD_LOCAL_CLASS), Constants.PUTFIELD)); il.redirectBranches(ih, ihPost); mg.setMaxStack(); mg.setMaxLocals(); return mg; }
@Override public void generate(GenScope scope) { InstructionList il = scope.getInstructionList(); InstructionFactory ifact = scope.getInstructionFactory(); ConstantPoolGen cpg = scope.getConstantPool(); LocalVariableGen lvg = scope.newLocalVariable(this, Type.OBJECT); // TODO: I'm going to assume that there is an optional kindOf and // and p() predicate. if (this.getPredicates().size() > 2) throw new UnsupportedOperationException("QMatchJVMGen. Only 2 fixed predicates implemented."); KindOfPredicate kindOf = null; PropertyEqualsPredicate prop = null; if (getPredicates().get(0) instanceof KindOfPredicate) { kindOf = (KindOfPredicate) getPredicates().get(0); prop = (PropertyEqualsPredicate) getPredicates().get(1); } else { prop = (PropertyEqualsPredicate) getPredicates().get(0); } // Create the object, then the parameters of the constructor String requestClass = "org.eclectic.idc.jvm.runtime.RequestKindProperty"; il.append(ifact.createNew(requestClass)); il.append(InstructionConstants.DUP); scope.generateGetModelManager(); if (kindOf == null) { il.append(InstructionConstants.ACONST_NULL); } else { ReadMetaJVMGen readMeta = new ReadMetaJVMGen(); readMeta.setClassName(kindOf.getClassName()); readMeta.setModel(kindOf.getModel()); readMeta.setName("_readMeta_for" + getName()); readMeta.setFile(this.getFile()); readMeta.setColumn(this.getColumn()); readMeta.setRow(this.getRow()); readMeta.generate(scope); scope.loadVariable(readMeta, il); } il.append(ifact.createConstant(prop.getPropertyName())); scope.loadVariable(prop.getValue(), il); // In the stack: IdcMetaclass, featureName, value + receptor x 2 il.append( ifact.createInvoke( requestClass, "<init>", Type.VOID, new Type[] { DefaultTypes.ModelManager, DefaultTypes.IdcMetaclass, Type.STRING, Type.OBJECT }, Constants.INVOKESPECIAL)); if (getGetterClosure() != null) { il.append(InstructionConstants.DUP); scope.loadVariable(getGetterClosure(), il); il.append( ifact.createInvoke( requestClass, "setGetterClosure", Type.VOID, new Type[] {DefaultTypes.IClosure}, Constants.INVOKEVIRTUAL)); } // Generate debug info il.append(InstructionConstants.DUP); if (getFile() == null) { il.append(InstructionConstants.ACONST_NULL); } else { il.append(ifact.createConstant(getFile())); } il.append(ifact.createConstant(getRow())); il.append(ifact.createConstant(getColumn())); il.append( ifact.createInvoke( requestClass, "setDebugInfo", Type.VOID, new Type[] {Type.STRING, Type.INT, Type.INT}, Constants.INVOKEVIRTUAL)); // End-of debug info QueueJVMGen jvmQ = (QueueJVMGen) getQueue(); CommonGen.generateGetQueue(scope, jvmQ); il.append(InstructionConstants.SWAP); il.append( ifact.createInvoke( DefaultTypes.ContinuationResolverHelper.getClassName(), "requestAndWait", Type.OBJECT, new Type[] {DefaultTypes.HistoryQueue, DefaultTypes.IRequest}, Constants.INVOKESTATIC)); // il.append(ifact.createInvoke(jvmQ.getClassName(), // "requestAndWait", Type.OBJECT, new Type[] { DefaultTypes.IRequest }, // Constants.INVOKEVIRTUAL)); // il.append(InstructionConstants.DUP); // CommonGen.print(il, ifact); il.append(new ASTORE(lvg.getIndex())); }
public Instruction createInstructionNew(Element inst) { String t = inst.getAttributeValue("type"); return _factory.createNew(t); }
/** * Creates a proxy method for the original method specified. This method has the same signature as * the original method and catches the invocation for further processing by the framework before * redirecting to the original method. * * @todo pass the 'class' as a Class instance not a String to the join point. Add the class field * to the class using BCEL (see AdviseStaticMethodTransformer.java) * @param cp the ConstantPoolGen * @param cg the ClassGen * @param originalMethod the current method * @param factory the objectfactory * @param methodId the id of the current method in the lookup tabl * @param methodSequence the methods sequence number * @param accessFlags the access flags of the original method * @param uuid the uuid for the weave model defining the pointcut * @param controllerClassName the class name of the controller class to use * @return the proxy method */ private Method createProxyMethod( final ConstantPoolGen cp, final ClassGen cg, final MethodGen originalMethod, final InstructionFactory factory, final int methodId, final int methodSequence, final int accessFlags, final String uuid, final String controllerClassName) { InstructionList il = new InstructionList(); String joinPoint = getJoinPointName(originalMethod.getMethod(), methodSequence); final MethodGen method = new MethodGen( accessFlags, Type.getReturnType(originalMethod.getSignature()), Type.getArgumentTypes(originalMethod.getSignature()), originalMethod.getArgumentNames(), originalMethod.getName(), cg.getClassName(), il, cp); String[] exceptions = originalMethod.getExceptions(); for (int i = 0; i < exceptions.length; i++) { method.addException(exceptions[i]); } int indexParam = 1; int indexStack = 0; int indexJoinPoint = Type.getArgumentTypes(originalMethod.getSignature()).length * 2 + 1; // if (threadLocal == null) { // threadLocal = new SerializableThreadLocal(); // } il.append(factory.createLoad(Type.OBJECT, 0)); il.append( factory.createFieldAccess( cg.getClassName(), joinPoint, new ObjectType(TransformationUtil.THREAD_LOCAL_CLASS), Constants.GETFIELD)); BranchInstruction ifNotNull = factory.createBranchInstruction(Constants.IFNONNULL, null); il.append(ifNotNull); il.append(factory.createLoad(Type.OBJECT, 0)); il.append(factory.createNew(TransformationUtil.THREAD_LOCAL_CLASS)); il.append(InstructionConstants.DUP); il.append( factory.createInvoke( TransformationUtil.THREAD_LOCAL_CLASS, "<init>", Type.VOID, Type.NO_ARGS, Constants.INVOKESPECIAL)); il.append( factory.createFieldAccess( cg.getClassName(), joinPoint.toString(), new ObjectType(TransformationUtil.THREAD_LOCAL_CLASS), Constants.PUTFIELD)); // Object joinPoint = ___jp.get(); BranchInstruction biIfNotNull = null; InstructionHandle ihIfNotNull = null; ifNotNull.setTarget(il.append(factory.createLoad(Type.OBJECT, 0))); il.append( factory.createFieldAccess( cg.getClassName(), joinPoint.toString(), new ObjectType(TransformationUtil.THREAD_LOCAL_CLASS), Constants.GETFIELD)); il.append( factory.createInvoke( TransformationUtil.THREAD_LOCAL_CLASS, "get", Type.OBJECT, Type.NO_ARGS, Constants.INVOKEVIRTUAL)); il.append(factory.createStore(Type.OBJECT, indexJoinPoint)); il.append(factory.createLoad(Type.OBJECT, indexJoinPoint)); // if (joinPoint == null) { biIfNotNull = factory.createBranchInstruction(Constants.IFNONNULL, null); il.append(biIfNotNull); // joinPoint = new WeakReference(new MemberMethodJoinPoint(uuid, this, "foo.bar.Baz", 10)); // il.append(factory.createNew(TransformationUtil.WEAK_REFERENCE_CLASS)); // il.append(InstructionConstants.DUP); il.append(factory.createNew(TransformationUtil.MEMBER_METHOD_JOIN_POINT_CLASS)); il.append(InstructionConstants.DUP); il.append(new PUSH(cp, uuid)); il.append(factory.createLoad(Type.OBJECT, 0)); il.append(new PUSH(cp, cg.getClassName())); il.append(new PUSH(cp, methodId)); il.append(new PUSH(cp, controllerClassName)); il.append( factory.createInvoke( TransformationUtil.MEMBER_METHOD_JOIN_POINT_CLASS, "<init>", Type.VOID, new Type[] {Type.STRING, Type.OBJECT, Type.STRING, Type.INT, Type.STRING}, Constants.INVOKESPECIAL)); il.append(factory.createStore(Type.OBJECT, indexJoinPoint)); // threadLocal.set(joinPoint); il.append(factory.createLoad(Type.OBJECT, 0)); il.append( factory.createFieldAccess( cg.getClassName(), joinPoint.toString(), new ObjectType(TransformationUtil.THREAD_LOCAL_CLASS), Constants.GETFIELD)); il.append(factory.createLoad(Type.OBJECT, indexJoinPoint)); il.append( factory.createInvoke( TransformationUtil.THREAD_LOCAL_CLASS, "set", Type.VOID, new Type[] {Type.OBJECT}, Constants.INVOKEVIRTUAL)); ihIfNotNull = il.append(factory.createLoad(Type.OBJECT, indexJoinPoint)); indexJoinPoint += 2; il.append(factory.createCheckCast(TransformationUtil.MEMBER_METHOD_JOIN_POINT_TYPE)); il.append(factory.createStore(Type.OBJECT, indexJoinPoint)); biIfNotNull.setTarget(ihIfNotNull); // if we have parameters, wrap them up if (Type.getArgumentTypes(originalMethod.getSignature()).length != 0) { // create and allocate the parameters array il.append(new PUSH(cp, Type.getArgumentTypes(originalMethod.getSignature()).length)); il.append(factory.createNewArray(Type.OBJECT, (short) 1)); il.append(InstructionConstants.DUP); il.append(new PUSH(cp, indexStack)); indexStack++; // add all the parameters, wrap the primitive types in their object counterparts for (int count = 0; count < Type.getArgumentTypes(originalMethod.getSignature()).length; count++) { String wrapperClass = null; BasicType type = null; boolean hasLongOrDouble = false; if (Type.getArgumentTypes(originalMethod.getSignature())[count] instanceof ObjectType || Type.getArgumentTypes(originalMethod.getSignature())[count] instanceof ArrayType) { // we have an object or an array il.append(factory.createLoad(Type.OBJECT, indexParam)); il.append(InstructionConstants.AASTORE); indexParam++; } else if (Type.getArgumentTypes(originalMethod.getSignature())[count] instanceof ArrayType) { // we have an array il.append(factory.createLoad(Type.OBJECT, indexParam)); il.append(InstructionConstants.AASTORE); indexParam++; } else if (Type.getArgumentTypes(originalMethod.getSignature())[count] instanceof BasicType) { hasLongOrDouble = false; // we have a primitive type if ((Type.getArgumentTypes(originalMethod.getSignature())[count]).equals(Type.LONG)) { wrapperClass = "java.lang.Long"; type = Type.LONG; hasLongOrDouble = true; } else if ((Type.getArgumentTypes(originalMethod.getSignature())[count]) .equals(Type.INT)) { wrapperClass = "java.lang.Integer"; type = Type.INT; } else if ((Type.getArgumentTypes(originalMethod.getSignature())[count]) .equals(Type.SHORT)) { wrapperClass = "java.lang.Short"; type = Type.SHORT; } else if ((Type.getArgumentTypes(originalMethod.getSignature())[count]) .equals(Type.DOUBLE)) { wrapperClass = "java.lang.Double"; type = Type.DOUBLE; hasLongOrDouble = true; } else if ((Type.getArgumentTypes(originalMethod.getSignature())[count]) .equals(Type.FLOAT)) { wrapperClass = "java.lang.Float"; type = Type.FLOAT; } else if ((Type.getArgumentTypes(originalMethod.getSignature())[count]) .equals(Type.CHAR)) { wrapperClass = "java.lang.Character"; type = Type.CHAR; } else if ((Type.getArgumentTypes(originalMethod.getSignature())[count]) .equals(Type.BYTE)) { wrapperClass = "java.lang.Byte"; type = Type.BYTE; } else if ((Type.getArgumentTypes(originalMethod.getSignature())[count]) .equals(Type.BOOLEAN)) { wrapperClass = "java.lang.Boolean"; type = Type.BOOLEAN; } else { throw new RuntimeException( "unknown parameter type: " + Type.getArgumentTypes(originalMethod.getSignature())[count]); } il.append(factory.createNew(wrapperClass)); il.append(InstructionConstants.DUP); il.append(factory.createLoad(type, indexParam)); il.append( factory.createInvoke( wrapperClass, "<init>", Type.VOID, new Type[] {type}, Constants.INVOKESPECIAL)); il.append(InstructionConstants.AASTORE); indexParam++; } // end handle basic or object type if (count != Type.getArgumentTypes(originalMethod.getSignature()).length - 1) { // if we don't have the last parameter, create the parameter on the stack il.append(InstructionConstants.DUP); il.append(new PUSH(cp, indexStack)); indexStack++; // long or double needs two registers to fit if (hasLongOrDouble) indexParam++; } } // create the object array il.append(factory.createStore(Type.OBJECT, indexParam)); // if threadsafe grab the newly retrieved local join point field from the stack il.append(factory.createLoad(Type.OBJECT, indexJoinPoint)); // invoke joinPoint.setParameter(..) il.append(factory.createLoad(Type.OBJECT, indexParam)); il.append( factory.createInvoke( TransformationUtil.MEMBER_METHOD_JOIN_POINT_CLASS, "setParameters", Type.VOID, new Type[] {new ArrayType(Type.OBJECT, 1)}, Constants.INVOKEVIRTUAL)); indexParam++; } // end - if parameters.length != 0 // if threadsafe grab the newly retrieved local join point field from the stack il.append(factory.createLoad(Type.OBJECT, indexJoinPoint)); il.append( factory.createInvoke( TransformationUtil.MEMBER_METHOD_JOIN_POINT_CLASS, "proceed", Type.OBJECT, Type.NO_ARGS, Constants.INVOKEVIRTUAL)); if (!Type.getReturnType(originalMethod.getSignature()).equals(Type.VOID)) { // create the result from the invocation il.append(factory.createStore(Type.OBJECT, indexParam)); il.append(factory.createLoad(Type.OBJECT, indexParam)); // cast the result and return it, if the return type is a // primitive type, retrieve it from the wrapped object first // unless the return object is null (AW-100) if (Type.getReturnType(originalMethod.getSignature()) instanceof BasicType) { if (Type.getReturnType(originalMethod.getSignature()).equals(Type.VOID)) {; // skip } else { BranchInstruction ifNullBranch = factory.createBranchInstruction(Constants.IFNONNULL, null); InstructionHandle elseBranch = null; il.append(ifNullBranch); if (Type.getReturnType(originalMethod.getSignature()).equals(Type.LONG)) { il.append(new PUSH(cp, 0L)); il.append(factory.createReturn(Type.LONG)); elseBranch = il.append(factory.createLoad(Type.OBJECT, indexParam)); il.append(factory.createCheckCast(new ObjectType("java.lang.Long"))); il.append( factory.createInvoke( "java.lang.Long", "longValue", Type.LONG, Type.NO_ARGS, Constants.INVOKEVIRTUAL)); } else if (Type.getReturnType(originalMethod.getSignature()).equals(Type.INT)) { il.append(new PUSH(cp, 0)); il.append(factory.createReturn(Type.INT)); elseBranch = il.append(factory.createLoad(Type.OBJECT, indexParam)); il.append(factory.createCheckCast(new ObjectType("java.lang.Integer"))); il.append( factory.createInvoke( "java.lang.Integer", "intValue", Type.INT, Type.NO_ARGS, Constants.INVOKEVIRTUAL)); } else if (Type.getReturnType(originalMethod.getSignature()).equals(Type.SHORT)) { il.append(new PUSH(cp, (short) 0)); il.append(factory.createReturn(Type.SHORT)); elseBranch = il.append(factory.createLoad(Type.OBJECT, indexParam)); il.append(factory.createCheckCast(new ObjectType("java.lang.Short"))); il.append( factory.createInvoke( "java.lang.Short", "shortValue", Type.SHORT, Type.NO_ARGS, Constants.INVOKEVIRTUAL)); } else if (Type.getReturnType(originalMethod.getSignature()).equals(Type.DOUBLE)) { il.append(new PUSH(cp, 0.0d)); il.append(factory.createReturn(Type.DOUBLE)); elseBranch = il.append(factory.createLoad(Type.OBJECT, indexParam)); il.append(factory.createCheckCast(new ObjectType("java.lang.Double"))); il.append( factory.createInvoke( "java.lang.Double", "doubleValue", Type.DOUBLE, Type.NO_ARGS, Constants.INVOKEVIRTUAL)); } else if (Type.getReturnType(originalMethod.getSignature()).equals(Type.FLOAT)) { il.append(new PUSH(cp, 0.0f)); il.append(factory.createReturn(Type.FLOAT)); elseBranch = il.append(factory.createLoad(Type.OBJECT, indexParam)); il.append(factory.createCheckCast(new ObjectType("java.lang.Float"))); il.append( factory.createInvoke( "java.lang.Float", "floatValue", Type.FLOAT, Type.NO_ARGS, Constants.INVOKEVIRTUAL)); } else if (Type.getReturnType(originalMethod.getSignature()).equals(Type.CHAR)) { il.append(new PUSH(cp, '\u0000')); il.append(factory.createReturn(Type.CHAR)); elseBranch = il.append(factory.createLoad(Type.OBJECT, indexParam)); il.append(factory.createCheckCast(new ObjectType("java.lang.Character"))); il.append( factory.createInvoke( "java.lang.Character", "charValue", Type.CHAR, Type.NO_ARGS, Constants.INVOKEVIRTUAL)); } else if (Type.getReturnType(originalMethod.getSignature()).equals(Type.BYTE)) { il.append(new PUSH(cp, (byte) 0)); il.append(factory.createReturn(Type.BYTE)); elseBranch = il.append(factory.createLoad(Type.OBJECT, indexParam)); il.append(factory.createCheckCast(new ObjectType("java.lang.Byte"))); il.append( factory.createInvoke( "java.lang.Byte", "byteValue", Type.BYTE, Type.NO_ARGS, Constants.INVOKEVIRTUAL)); } else if (Type.getReturnType(originalMethod.getSignature()).equals(Type.BOOLEAN)) { il.append(new PUSH(cp, false)); il.append(factory.createReturn(Type.BOOLEAN)); elseBranch = il.append(factory.createLoad(Type.OBJECT, indexParam)); il.append(factory.createCheckCast(new ObjectType("java.lang.Boolean"))); il.append( factory.createInvoke( "java.lang.Boolean", "booleanValue", Type.BOOLEAN, Type.NO_ARGS, Constants.INVOKEVIRTUAL)); } else { throw new Error( "unknown return type: " + Type.getReturnType(originalMethod.getSignature())); } ifNullBranch.setTarget(elseBranch); } } else { // cast the result to the right type il.append( factory.createCast(Type.OBJECT, Type.getReturnType(originalMethod.getSignature()))); } } il.append(factory.createReturn(Type.getReturnType(originalMethod.getSignature()))); method.setMaxStack(); method.setMaxLocals(); return method.getMethod(); }