@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(); }
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])); } }
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(); } }
@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(); } } }
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; }
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; }