// Only handles rectangle multi dim arrays now public static void acceptInit(JMethodDeclaration init, Hashtable constants) { JBlock body = init.getBody(); JFormalParameter[] params = init.getParameters(); for (int i = params.length - 1; i >= 0; i--) { LinkedList<JIntLiteral> dims = new LinkedList<JIntLiteral>(); Object val = constants.get(params[i]); Object temp = val; while (temp instanceof Object[]) { dims.add(new JIntLiteral(((Object[]) temp).length)); temp = ((Object[]) temp)[0]; } if (dims.size() > 0) { dumpAssign(val, body, new JLocalVariableExpression(null, params[i])); body.addStatementFirst( new JExpressionStatement( null, new JAssignmentExpression( null, new JLocalVariableExpression(null, params[i]), new JNewArrayExpression( null, params[i].getType(), dims.toArray(new JExpression[0]), null)), null)); } } }
private static void dumpAssign(Object array, JBlock body, JExpression prefix) { if (array instanceof JExpression) { if (((JExpression) array).isConstant()) body.addStatementFirst( new JExpressionStatement( null, new JAssignmentExpression(null, prefix, (JExpression) array), null)); } else if (array instanceof Object[]) { for (int i = ((Object[]) array).length - 1; i >= 0; i--) dumpAssign( ((Object[]) array)[i], body, new JArrayAccessExpression(null, prefix, new JIntLiteral(i))); } else { System.err.println("WARNING: Non Array input to dumpAssign" + array); } }
private InjectionNode innerGenerateProxyCode(InjectionNode injectionNode) { AOPProxyAspect aopProxyAspect = injectionNode.getAspect(AOPProxyAspect.class); JDefinedClass definedClass; String proxyClassName = injectionNode.getClassName() + "_AOPProxy"; ASTInjectionAspect injectionAspect = injectionNode.getAspect(ASTInjectionAspect.class); ConstructorInjectionPoint constructorInjectionPoint = injectionAspect.getConstructorInjectionPoint(); ConstructorInjectionPoint proxyConstructorInjectionPoint = new ConstructorInjectionPoint(ASTAccessModifier.PUBLIC); try { definedClass = codeModel._class(JMod.PUBLIC, proxyClassName, ClassType.CLASS); annotateGeneratedClass(definedClass); // extending injectionNode definedClass._extends(codeModel.ref(injectionNode.getClassName())); // copy constructor elements and add aop interceptors JMethod constructor = definedClass.constructor(JMod.PUBLIC); // converting exceptions into runtime exceptions proxyConstructorInjectionPoint.addThrows(constructorInjectionPoint.getThrowsTypes()); for (ASTType throwType : constructorInjectionPoint.getThrowsTypes()) { constructor._throws(codeModel.ref(throwType.getName())); } JBlock constructorBody = constructor.body(); List<JVar> superArguments = new ArrayList<JVar>(); for (InjectionNode node : constructorInjectionPoint.getInjectionNodes()) { String paramName = namer.generateName(node); JVar param = constructor.param(codeModel.ref(node.getClassName()), paramName); superArguments.add(param); proxyConstructorInjectionPoint.addInjectionNode(node); } // super construction JInvocation constructorInvocation = constructorBody.invoke(SUPER_REF); for (JVar paramArgument : superArguments) { constructorInvocation.arg(paramArgument); } // method interceptors Map<ASTMethod, Map<InjectionNode, JFieldVar>> interceptorFields = new HashMap<ASTMethod, Map<InjectionNode, JFieldVar>>(); for (Map.Entry<ASTMethod, Set<InjectionNode>> methodInterceptorEntry : aopProxyAspect.getMethodInterceptors().entrySet()) { buildMethodInterceptor( definedClass, proxyConstructorInjectionPoint, constructor, constructorBody, interceptorFields, methodInterceptorEntry); } } catch (JClassAlreadyExistsException e) { logger.error("JClassAlreadyExistsException while building AOP Proxy", e); } catch (ClassNotFoundException e) { logger.error("ClassNotFoundException while building AOP Proxy", e); } return buildProxyInjectionNode( injectionNode, proxyClassName, injectionAspect, proxyConstructorInjectionPoint); }
private JExpression buildInterceptorChain( JDefinedClass definedClass, ASTMethod method, Map<ASTParameter, JVar> parameterMap, Set<InjectionNode> interceptors, Map<InjectionNode, JFieldVar> interceptorNameMap) { try { JDefinedClass methodExecutionClass = definedClass._class( JMod.PRIVATE | JMod.FINAL, namer.generateClassName(MethodInterceptorChain.MethodExecution.class)); methodExecutionClass._implements(MethodInterceptorChain.MethodExecution.class); // setup constructor with needed parameters JMethod constructor = methodExecutionClass.constructor(JMod.PUBLIC); JBlock constructorbody = constructor.body(); List<JExpression> methodParameters = new ArrayList<JExpression>(); for (ASTParameter parameter : method.getParameters()) { JType parameterType = parameterMap.get(parameter).type(); JVar param = constructor.param(parameterType, namer.generateName(parameterType)); JFieldVar field = methodExecutionClass.field( JMod.PRIVATE, parameterType, namer.generateName(parameterType)); constructorbody.assign(field, param); methodParameters.add(field); } // getMethod() JMethod getMethod = methodExecutionClass.method( JMod.PUBLIC, Method.class, MethodInterceptorChain.MethodExecution.GET_METHOD); JInvocation getMethodInvocation = definedClass.dotclass().invoke(CLASS_GET_METHOD).arg(method.getName()); getMethod.body()._return(getMethodInvocation); getMethod._throws(NoSuchMethodException.class); for (ASTParameter astParameter : method.getParameters()) { getMethodInvocation.arg(codeModel.ref(astParameter.getASTType().getName()).dotclass()); } // invoke() JMethod invokeMethod = methodExecutionClass.method( JMod.PUBLIC, Object.class, MethodInterceptorChain.MethodExecution.INVOKE); // add all throws of contained method for (ASTType throwable : method.getThrowsTypes()) { invokeMethod._throws(codeModel.ref(throwable.getName())); } JInvocation superCall = definedClass.staticRef(SUPER_REF).invoke(method.getName()); for (JExpression methodParam : methodParameters) { superCall.arg(methodParam); } if (method.getReturnType().equals(ASTVoidType.VOID)) { invokeMethod.body().add(superCall); invokeMethod.body()._return(JExpr._null()); } else { invokeMethod.body()._return(superCall); } JInvocation methodExecutionInvocation = JExpr._new(methodExecutionClass); for (ASTParameter astParameter : method.getParameters()) { methodExecutionInvocation.arg(parameterMap.get(astParameter)); } JInvocation newInterceptorInvocation = JExpr._new(codeModel.ref(MethodInterceptorChain.class)) .arg(methodExecutionInvocation) .arg(JExpr._this()); for (InjectionNode interceptor : interceptors) { newInterceptorInvocation.arg(interceptorNameMap.get(interceptor)); } return newInterceptorInvocation; } catch (JClassAlreadyExistsException e) { throw new TransfuseAnalysisException("Class already defined while generating inner class", e); } }
private void buildMethodInterceptor( JDefinedClass definedClass, ConstructorInjectionPoint proxyConstructorInjectionPoint, JMethod constructor, JBlock constructorBody, Map<ASTMethod, Map<InjectionNode, JFieldVar>> interceptorFields, Map.Entry<ASTMethod, Set<InjectionNode>> methodInterceptorEntry) throws ClassNotFoundException { ASTMethod method = methodInterceptorEntry.getKey(); if (method.getAccessModifier().equals(ASTAccessModifier.PRIVATE)) { throw new TransfuseAnalysisException("Unable to provide AOP on private methods"); } if (!interceptorFields.containsKey(methodInterceptorEntry.getKey())) { interceptorFields.put( methodInterceptorEntry.getKey(), new HashMap<InjectionNode, JFieldVar>()); } Map<InjectionNode, JFieldVar> injectionNodeInstanceNameMap = interceptorFields.get(methodInterceptorEntry.getKey()); // setup interceptor fields for (InjectionNode interceptorInjectionNode : methodInterceptorEntry.getValue()) { String interceptorInstanceName = namer.generateName(interceptorInjectionNode); JFieldVar interceptorField = definedClass.field( JMod.PRIVATE, codeModel.ref(interceptorInjectionNode.getClassName()), interceptorInstanceName); injectionNodeInstanceNameMap.put(interceptorInjectionNode, interceptorField); JVar interceptorParam = constructor.param( codeModel.ref(interceptorInjectionNode.getClassName()), namer.generateName(interceptorInjectionNode)); constructorBody.assign(interceptorField, interceptorParam); proxyConstructorInjectionPoint.addInjectionNode(interceptorInjectionNode); } JType returnType = codeModel.parseType(method.getReturnType().getName()); JMethod methodDeclaration = definedClass.method( method.getAccessModifier().getCodeModelJMod(), returnType, method.getName()); JBlock body = methodDeclaration.body(); // define method parameter Map<ASTParameter, JVar> parameterMap = new HashMap<ASTParameter, JVar>(); for (ASTParameter parameter : method.getParameters()) { parameterMap.put( parameter, methodDeclaration.param( JMod.FINAL, codeModel.ref(parameter.getASTType().getName()), namer.generateName(parameter.getASTType()))); } // aop interceptor Map<InjectionNode, JFieldVar> interceptorNameMap = interceptorFields.get(methodInterceptorEntry.getKey()); JArray paramArray = JExpr.newArray(codeModel.ref(Object.class)); for (ASTParameter astParameter : method.getParameters()) { paramArray.add(parameterMap.get(astParameter)); } JInvocation interceptorInvocation = buildInterceptorChain( definedClass, method, parameterMap, methodInterceptorEntry.getValue(), interceptorNameMap) .invoke("invoke"); interceptorInvocation.arg(paramArray); if (method.getReturnType().equals(ASTVoidType.VOID)) { body.add(interceptorInvocation); } else { body._return(JExpr.cast(returnType.boxify(), interceptorInvocation)); } }
/** * Make a work function for a joiner * * @param joiner the InputSliceNode that we are generating code for. * @param backEndBits way to refer to other portions of backend * @param joiner_code place to put code */ public static void makeJoinerWork( InputSliceNode joiner, BackEndFactory backEndBits, CodeStoreHelper joiner_code) { JMethodDeclaration joinerWork; // the work function will need a temporary variable ALocalVariable t = ALocalVariable.makeTmp(joiner.getEdgeToNext().getType()); Channel downstream = backEndBits.getChannel(joiner.getEdgeToNext()); // the body of the work method JBlock body = new JBlock(); if (backEndBits.sliceNeedsJoinerCode(joiner.getParent())) { // There should be generated code for the joiner // state machine in the CodeStoreHelper as the only method. // // generated code is // T tmp; // tmp = joiner_code(); // push(tmp); // // TODO: inline the joiner code at the call site, // if inlining, delete joiner code after inlining leaving // only this method in the helper. assert joiner_code.getMethods().length == 1; JMethodDeclaration callable_joiner = joiner_code.getMethods()[0]; body.addStatement(t.getDecl()); body.addStatement( new JExpressionStatement( new JAssignmentExpression( t.getRef(), new JMethodCallExpression(callable_joiner.getName(), new JExpression[0])))); body.addStatement( new JExpressionStatement( new JMethodCallExpression( downstream.pushMethodName(), new JExpression[] {t.getRef()}))); } else { // slice does not need joiner code, so just transfer from upstream // to downstream buffer. // // generated code is // T tmp; // tmp = pop(); // push(tmp); // assert joiner.getWidth() == 1; Channel upstream = backEndBits.getChannel(joiner.getSingleEdge()); body.addStatement(t.getDecl()); body.addStatement( new JExpressionStatement( new JAssignmentExpression( t.getRef(), new JMethodCallExpression(upstream.popMethodName(), new JExpression[0])))); body.addStatement( new JExpressionStatement( new JMethodCallExpression( downstream.pushMethodName(), new JExpression[] {t.getRef()}))); } joinerWork = new JMethodDeclaration( CStdType.Void, "_joinerWork_" + joiner.getNextFilter().getFilter().getName(), JFormalParameter.EMPTY, body); joiner_code.setWorkMethod(joinerWork); joiner_code.addMethod(joinerWork); }
/** * Create fields and code for a joiner, as follows. Do not create a joiner if all weights are 0: * this code fails rather than creating nonsensical kopi code. Note that this <b>always</b> * creates code, if you want to reuse any existing code call {@link #getJoinerCode(InputSliceNode, * BackEndFactory) getJoinerCode} instead. * * <pre> * joiner as a state machine, driven off arrays: * * / * joiner (unless single edge, just delegated to a channel * arity (4) and weight s but not duplication. * / * * T pop_1_M() {fprintf(stderr, "pop_1_M\n"); return 0;} * T pop_2_M() {fprintf(stderr, "pop_2_M\n"); return 0;} * T pop_4_M() {fprintf(stderr, "pop_4_M\n"); return 0;} * * * static int joiner_M_edge = 4 - 1; * static int joiner_M_weight = 0; * * static inline T joiner_M() { * * / * attempt to place const either applies it to function, or gives parse error * do we need to move this to file scope to convince inliner to work on joiner_M? * / * static T (*pops[4])() = { * pop_1_M, * pop_2_M, * 0, / * 0-weight edge * / * pop_4_M * }; * * static const int weights[4] = {2, 1, 0, 2}; * * while (joiner_M_weight == 0) { / * "if" if do not generate for 0-length edges. * / * joiner_M_edge = (joiner_M_edge + 1) % 4; * joiner_M_weight = weights[joiner_M_edge]; * } * joiner_M_weight--; * * return pops[joiner_M_edge](); * } * * joiner as a case statement, which is what we implement: * * * static int joiner_M_unrolled_edge = 3 - 1; * static int joiner_M_unrolled_weight = 0; * * static inline T joiner_M_unrolled() { * * static const int weights[3] = {2-1, 1-1, 2-1}; * * if (--joiner_M_unrolled_weight < 0) { * joiner_M_unrolled_edge = (joiner_M_unrolled_edge + 1) % 3; * joiner_M_unrolled_weight = weights[joiner_M_unrolled_edge]; * } * * switch (joiner_M_unrolled_edge) { * case 0: * return pop_1_M(); * case 1: * return pop_2_M(); * case 2: * return pop_4_M(); * } * } * </pre> * * @param joiner An InputSliceNode specifying joiner weights and edges. * @param backEndBits to get info from appropriate BackEndFactory * @param helper CodeStoreHelper to get the fields and method implementing the joiner */ private static void makeJoinerCode( InputSliceNode joiner, BackEndFactory backEndBits, CodeStoreHelper helper) { String joiner_name = "_joiner_" + ProcessFilterSliceNode.getUid(); String joiner_method_name = joiner_name + joiner.getNextFilter().getFilter().getName(); // size is number of edges with non-zero weight. int size = 0; for (int w : joiner.getWeights()) { if (w != 0) { size++; } } assert size > 0 : "asking for code generation for null joiner"; String edge_name = joiner_name + "_edge"; String weight_name = joiner_name + "_weight"; JVariableDefinition edgeVar = new JVariableDefinition( at.dms.kjc.Constants.ACC_STATIC, CStdType.Integer, edge_name, new JIntLiteral(size - 1)); JFieldDeclaration edgeDecl = new JFieldDeclaration(edgeVar); JFieldAccessExpression edgeExpr = new JFieldAccessExpression(edge_name); JVariableDefinition weightVar = new JVariableDefinition( at.dms.kjc.Constants.ACC_STATIC, CStdType.Integer, weight_name, new JIntLiteral(0)); JFieldDeclaration weightDecl = new JFieldDeclaration(weightVar); JFieldAccessExpression weightExpr = new JFieldAccessExpression(weight_name); JIntLiteral[] weightVals = new JIntLiteral[size]; { int i = 0; for (int w : joiner.getWeights()) { if (w != 0) { weightVals[i++] = new JIntLiteral(w - 1); } } } JVariableDefinition weightsArray = new JVariableDefinition( at.dms.kjc.Constants.ACC_STATIC | at.dms.kjc.Constants.ACC_FINAL, // static const in C new CArrayType(CStdType.Integer, 1, new JExpression[] {new JIntLiteral(size)}), "weights", new JArrayInitializer(weightVals)); JLocalVariableExpression weightsExpr = new JLocalVariableExpression(weightsArray); JStatement next_edge_weight_stmt = new JIfStatement( null, new JRelationalExpression( at.dms.kjc.Constants.OPE_LT, new JPrefixExpression(null, at.dms.kjc.Constants.OPE_PREDEC, weightExpr), new JIntLiteral(0)), new JBlock( new JStatement[] { new JExpressionStatement( new JAssignmentExpression( edgeExpr, new JModuloExpression( null, new JAddExpression(edgeExpr, new JIntLiteral(1)), new JIntLiteral(size)))), new JExpressionStatement( new JAssignmentExpression( weightExpr, new JArrayAccessExpression(weightsExpr, edgeExpr))) }), new JEmptyStatement(), null); JSwitchGroup[] cases = new JSwitchGroup[size]; // fill in later. JStatement switch_on_edge_stmt = new JSwitchStatement(null, edgeExpr, cases, null); { int i = 0; for (int j = 0; j < joiner.getWeights().length; j++) { if (joiner.getWeights()[j] != 0) { JMethodCallExpression pop = new JMethodCallExpression( backEndBits.getChannel(joiner.getSources()[j]).popMethodName(), new JExpression[0]); pop.setType(joiner.getType()); cases[i] = new JSwitchGroup( null, new JSwitchLabel[] {new JSwitchLabel(null, new JIntLiteral(i))}, new JStatement[] {new JReturnStatement(null, pop, null)}); i++; } } } JMethodDeclaration joiner_method = new JMethodDeclaration( null, at.dms.kjc.Constants.ACC_STATIC | at.dms.kjc.Constants.ACC_INLINE, joiner.getType(), joiner_method_name, new JFormalParameter[] {}, new CClassType[] {}, new JBlock(), null, null); JBlock joiner_block = joiner_method.getBody(); joiner_block.addStatement( new JVariableDeclarationStatement(new JVariableDefinition[] {weightsArray})); joiner_block.addStatement(next_edge_weight_stmt); joiner_block.addStatement(switch_on_edge_stmt); helper.addFields(new JFieldDeclaration[] {edgeDecl, weightDecl}); helper.addMethod(joiner_method); }