@Override
  public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef)
      throws IOException {
    ClassReader cls = context.getClassSource().get(methodRef.getClassName());
    MethodReader method = cls.getMethod(methodRef.getDescriptor());
    AnnotationReader providerAnnot = method.getAnnotations().get(MetadataProvider.class.getName());

    AnnotationReader refAnnot = method.getAnnotations().get(MetadataProviderRef.class.getName());
    methodRef = MethodReference.parse(refAnnot.getValue("value").getString());

    // Find and instantiate metadata generator
    ValueType generatorType = providerAnnot.getValue("value").getJavaClass();
    String generatorClassName = ((ValueType.Object) generatorType).getClassName();
    Class<?> generatorClass;
    try {
      generatorClass = Class.forName(generatorClassName, true, context.getClassLoader());
    } catch (ClassNotFoundException e) {
      context
          .getDiagnostics()
          .error(
              new CallLocation(methodRef),
              "Can't find metadata provider class {{c0}}",
              generatorClassName);
      return;
    }
    Constructor<?> cons;
    try {
      cons = generatorClass.getConstructor();
    } catch (NoSuchMethodException e) {
      context
          .getDiagnostics()
          .error(
              new CallLocation(methodRef),
              "Metadata generator {{c0}} does not have " + "a public no-arg constructor",
              generatorClassName);
      return;
    }
    MetadataGenerator generator;
    try {
      generator = (MetadataGenerator) cons.newInstance();
    } catch (IllegalAccessException | InstantiationException | InvocationTargetException e) {
      context
          .getDiagnostics()
          .error(
              new CallLocation(methodRef),
              "Error instantiating metadata " + "generator {{c0}}",
              generatorClassName);
      return;
    }
    DefaultMetadataGeneratorContext metadataContext =
        new DefaultMetadataGeneratorContext(
            context.getClassSource(), context.getClassLoader(), context.getProperties(), context);

    // Generate resource loader
    Resource resource = generator.generateMetadata(metadataContext, methodRef);
    writer.append("return ");
    ResourceWriterHelper.write(writer, resource);
    writer.append(';').softNewLine();
  }
예제 #2
0
 public void addEntryPoint(MethodReference methodRef, String... argumentTypes) {
   ValueType[] parameters = methodRef.getDescriptor().getParameterTypes();
   if (parameters.length + 1 != argumentTypes.length) {
     throw new IllegalArgumentException(
         "argumentTypes length does not match the number of method's arguments");
   }
   MethodDependency method = linkMethod(methodRef, null);
   method.use();
   DependencyNode[] varNodes = method.getVariables();
   varNodes[0].propagate(getType(methodRef.getClassName()));
   for (int i = 0; i < argumentTypes.length; ++i) {
     varNodes[i + 1].propagate(getType(argumentTypes[i]));
   }
 }
예제 #3
0
  public void submitMethod(MethodReference methodRef, Program program) {
    if (!completing) {
      ClassHolder cls = classSource.get(methodRef.getClassName());

      if (cls == null) {
        throw new IllegalArgumentException("Class not found: " + methodRef.getClassName());
      }
      if (cls.getMethod(methodRef.getDescriptor()) != null) {
        throw new IllegalArgumentException("Method already exists: " + methodRef.getClassName());
      }
      MethodHolder method = new MethodHolder(methodRef.getDescriptor());
      method.getModifiers().add(ElementModifier.STATIC);
      method.setProgram(ProgramUtils.copy(program));
      new UnreachableBasicBlockEliminator().optimize(program);
      cls.addMethod(method);
    } else {
      MethodDependency dep = getMethod(methodRef);
      if (dep == null) {
        throw new IllegalArgumentException("Method was not reached: " + methodRef);
      }
      MethodHolder method = dep.method;

      if (!method.hasModifier(ElementModifier.NATIVE)) {
        throw new IllegalArgumentException("Method is not native: " + methodRef);
      }
      if (!dep.used) {
        return;
      }
      method.getModifiers().remove(ElementModifier.NATIVE);
      method.setProgram(ProgramUtils.copy(program));
      new UnreachableBasicBlockEliminator().optimize(method.getProgram());

      dep.used = false;
      lock(dep, false);
      tasks.add(
          () -> {
            DependencyGraphBuilder graphBuilder =
                new DependencyGraphBuilder(DependencyChecker.this);
            graphBuilder.buildGraph(dep);
            dep.used = true;
          });

      processQueue();
    }
  }
예제 #4
0
 @Override
 public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef)
     throws IOException {
   switch (methodRef.getName()) {
     case "toJavaScript":
       generateToJavaScript(context, writer);
       break;
     case "fromJavaScript":
       generateFromJavaScript(context, writer);
       break;
   }
 }
 @Override
 public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef)
     throws IOException {
   if (methodRef.getClassName().endsWith("_stderr")) {
     if (methodRef.getName().equals("write")) {
       writer
           .append("$rt_putStderr(")
           .append(context.getParameterName(1))
           .append(");")
           .softNewLine();
     }
   } else if (methodRef.getClassName().endsWith("_stdout")) {
     if (methodRef.getName().equals("write")) {
       writer
           .append("$rt_putStdout(")
           .append(context.getParameterName(1))
           .append(");")
           .softNewLine();
     }
   }
 }
예제 #6
0
 private MethodDependency createMethodDep(MethodReference methodRef, MethodHolder method) {
   ValueType[] arguments = methodRef.getParameterTypes();
   int paramCount = arguments.length + 1;
   DependencyNode[] parameterNodes = new DependencyNode[arguments.length + 1];
   for (int i = 0; i < parameterNodes.length; ++i) {
     parameterNodes[i] = createNode();
     parameterNodes[i].method = methodRef;
     if (shouldLog) {
       parameterNodes[i].setTag(methodRef + ":" + i);
     }
   }
   DependencyNode resultNode;
   if (methodRef.getDescriptor().getResultType() == ValueType.VOID) {
     resultNode = null;
   } else {
     resultNode = createNode();
     resultNode.method = methodRef;
     if (shouldLog) {
       resultNode.setTag(methodRef + ":RESULT");
     }
   }
   DependencyNode thrown = createNode();
   thrown.method = methodRef;
   if (shouldLog) {
     thrown.setTag(methodRef + ":THROWN");
   }
   MethodDependency dep =
       new MethodDependency(
           this, parameterNodes, paramCount, resultNode, thrown, method, methodRef);
   if (method != null) {
     tasks.add(
         () -> {
           CallLocation caller = new CallLocation(dep.getMethod().getReference());
           linkClass(dep.getMethod().getOwnerName(), caller).initClass(caller);
         });
   }
   return dep;
 }
예제 #7
0
 private List<Instruction> transformInvoke(InvokeInstruction insn) {
   if (insn.getType() != InvocationType.VIRTUAL) {
     return null;
   }
   MethodReference method = insn.getMethod();
   if (method.getClassName().equals(ResourceArray.class.getName())
       || method.getClassName().equals(ResourceMap.class.getName())) {
     if (method.getName().equals("keys")) {
       return transformKeys(insn);
     }
     InvokeInstruction accessInsn = new InvokeInstruction();
     accessInsn.setType(InvocationType.SPECIAL);
     ValueType[] types = new ValueType[method.getDescriptor().parameterCount() + 2];
     types[0] = ValueType.object("java.lang.Object");
     System.arraycopy(
         method.getDescriptor().getSignature(),
         0,
         types,
         1,
         method.getDescriptor().parameterCount() + 1);
     accessInsn.setMethod(
         new MethodReference(ResourceAccessor.class.getName(), method.getName(), types));
     accessInsn.getArguments().add(insn.getInstance());
     accessInsn.getArguments().addAll(insn.getArguments());
     accessInsn.setReceiver(insn.getReceiver());
     return Arrays.asList(accessInsn);
   }
   ClassReader iface = innerSource.get(method.getClassName());
   if (iface == null
       || !innerSource.isSuperType(Resource.class.getName(), iface.getName()).orElse(false)) {
     return null;
   }
   if (method.getName().startsWith("get")) {
     if (method.getName().length() > 3) {
       return transformGetterInvocation(insn, getPropertyName(method.getName().substring(3)));
     }
   } else if (method.getName().startsWith("is")) {
     if (method.getName().length() > 2) {
       return transformGetterInvocation(insn, getPropertyName(method.getName().substring(2)));
     }
   } else if (method.getName().startsWith("set")) {
     if (method.getName().length() > 3) {
       return transformSetterInvocation(insn, getPropertyName(method.getName().substring(3)));
     }
   }
   return null;
 }