예제 #1
0
 // 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));
     }
   }
 }
예제 #2
0
 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);
   }
 }
예제 #3
0
  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);
  }
예제 #4
0
  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);
    }
  }
예제 #5
0
  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));
    }
  }
예제 #6
0
  /**
   * 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);
  }
예제 #7
0
  /**
   * 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);
  }