@Override public void started(DependencyAgent agent) { proxyClassLoader = new MetaprogrammingClassLoader(agent.getClassLoader()); describer = new MethodDescriber(agent.getDiagnostics(), agent.getClassSource()); MetaprogrammingImpl.classLoader = proxyClassLoader; MetaprogrammingImpl.classSource = agent.getClassSource(); MetaprogrammingImpl.hierarchy = agent.getClassHierarchy(); MetaprogrammingImpl.incrementalDependencies = agent.getIncrementalCache(); MetaprogrammingImpl.agent = agent; MetaprogrammingImpl.reflectContext = new ReflectContext(agent.getClassHierarchy(), proxyClassLoader); }
private String getAnnotationImplementor(DependencyAgent agent, String annotationType) { String implementorName = annotationType + "$$_impl"; if (agent.getClassSource().get(implementorName) == null) { ClassHolder implementor = createImplementor(agent.getClassHierarchy(), annotationType, implementorName); agent.submitClass(implementor); } return implementorName; }
private MethodHolder addReader(DependencyAgent agent, ClassReader cls) { MethodHolder readerMethod = new MethodHolder("getAnnotations", ValueType.parse(Annotation[].class)); readerMethod.setLevel(AccessLevel.PUBLIC); ProgramEmitter pe = ProgramEmitter.create(readerMethod, agent.getClassHierarchy()); List<AnnotationReader> annotations = new ArrayList<>(); for (AnnotationReader annot : cls.getAnnotations().all()) { ClassReader annotType = agent.getClassSource().get(annot.getType()); if (annotType == null) { continue; } AnnotationReader retention = annotType.getAnnotations().get(Retention.class.getName()); if (retention != null) { String retentionPolicy = retention.getValue("value").getEnumValue().getFieldName(); if (retentionPolicy.equals("RUNTIME")) { annotations.add(annot); } } } ValueEmitter array = pe.constructArray(Annotation.class, annotations.size()); for (int i = 0; i < annotations.size(); ++i) { array.setElement(i, generateAnnotationInstance(agent, pe, annotations.get(i))); } array.returnValue(); return readerMethod; }
private void processInvocation(DependencyAgent agent, CallLocation location, String functionClassName, String targetClassName, String methodName) { Diagnostics diagnostics = agent.getDiagnostics(); ClassHierarchy hierarchy = agent.getClassHierarchy(); boolean valid = true;
@Override public void methodReached(DependencyAgent agent, MethodDependency method) { switch (method.getReference().getName()) { case "invoke": case "instantiate": case "function": if (reachedFunctorMethods.add(method.getReference()) && !method.isMissing()) { for (int i = 0; i < method.getReference().parameterCount(); ++i) { DependencyNode node = method.getVariable(i); if (functorParamNodes.add(node)) { node.addConsumer(type -> { if (agent.getClassHierarchy().isSuperType(method.getMethod().getOwnerName(), type.getName(), false)) { reachFunctorMethods(agent, type.getName()); } }); } } } break; case "unwrapString": method.getResult().propagate(agent.getType("java.lang.String")); break; } }
private void createAnnotationClass(DependencyAgent agent, String className) { String readerClassName = className + "$$__annotations__$$"; if (agent.getClassSource().get(readerClassName) != null) { return; } ClassHolder cls = new ClassHolder(className + "$$__annotations__$$"); cls.setLevel(AccessLevel.PUBLIC); cls.setOwnerName("java.lang.Object"); cls.getInterfaces().add(PlatformAnnotationProvider.class.getName()); MethodHolder ctor = new MethodHolder("<init>", ValueType.VOID); ctor.setLevel(AccessLevel.PUBLIC); ProgramEmitter pe = ProgramEmitter.create(ctor, agent.getClassHierarchy()); ValueEmitter thisVar = pe.var(0, cls); thisVar.invokeSpecial(Object.class, "<init>").exit(); ClassReader annotatedClass = agent.getClassSource().get(className); cls.addMethod(ctor); cls.addMethod(addReader(agent, annotatedClass)); agent.submitClass(cls); }
@Override public void consume(DependencyType type) { if (!agent.getClassHierarchy().isSuperType(superMethod.getClassName(), type.getName(), false)) { return; } MethodReader method = agent.getClassSource().resolveImplementation(new MethodReference( type.getName(), superMethod.getDescriptor())); if (method == null) { return; } virtualMethods.add(method.getReference()); MethodDependency methodDep = agent.linkMethod(method.getReference()); methodDep.use(); for (int i = 0; i < methodDep.getParameterCount(); ++i) { allClassesNode.connect(methodDep.getVariable(i)); allClassesNode.connect(methodDep.getVariable(i).getArrayItem()); } } }
@Override public void completing(DependencyAgent agent) { for (MethodModel model : describer.getKnownMethods()) { ProgramEmitter pe = ProgramEmitter.create(model.getMethod().getDescriptor(), agent.getClassHierarchy()); ValueEmitter[] paramVars = new ValueEmitter[model.getMetaParameterCount()]; int offset = model.isStatic() ? 1 : 0; for (int i = 0; i < paramVars.length; ++i) { paramVars[i] = pe.var(i + offset, model.getMetaParameterType(i)); } if (model.getUsages().size() == 1) { emitSingleUsage(model, pe, paramVars); } else if (model.getUsages().isEmpty()) { if (model.getMethod().getReturnType() == ValueType.VOID) { pe.exit(); } else { pe.constantNull(Object.class).returnValue(); } } else { emitMultipleUsage(model, pe, agent, paramVars); } agent.submitMethod(model.getMethod(), new Optimizations().apply(pe.getProgram(), model.getMethod())); } }
ClassHierarchy hierarchy = callSite.getAgent().getClassHierarchy(); ClassReader samClass = hierarchy.getClassSource().get(samName); ProgramEmitter pe = ProgramEmitter.create(worker, callSite.getAgent().getClassHierarchy()); pe.setCurrentLocation(callerPe.getCurrentLocation()); ValueEmitter thisVar = pe.var(0, implementor);
@Override public void methodReached(DependencyAgent agent, MethodDependency method) { MethodReference ref = method.getReference(); MethodReference asyncRef = getAsyncReference(ref); MethodDependency asyncMethod = agent.linkMethod(asyncRef); method.addLocationListener(asyncMethod::addLocation); int paramCount = ref.parameterCount(); for (int i = 0; i <= paramCount; ++i) { method.getVariable(i).connect(asyncMethod.getVariable(i)); } asyncMethod.getVariable(paramCount + 1).propagate(agent.getType(AsyncCallbackWrapper.class.getName())); MethodDependency completeMethod = agent.linkMethod( new MethodReference(AsyncCallbackWrapper.class, "complete", Object.class, void.class)); if (method.getResult() != null) { completeMethod.getVariable(1).connect(method.getResult(), type -> agent.getClassHierarchy() .isSuperType(ref.getReturnType(), ValueType.object(type.getName()), false)); } completeMethod.use(); MethodDependency errorMethod = agent.linkMethod(new MethodReference(AsyncCallbackWrapper.class, "error", Throwable.class, void.class)); errorMethod.getVariable(1).connect(method.getThrown()); errorMethod.use(); agent.linkMethod(new MethodReference(AsyncCallbackWrapper.class, "create", AsyncCallback.class, AsyncCallbackWrapper.class)).use(); asyncMethod.use(); }
method.getVariable(i).connect(allClassesNode); method.getVariable(i).addConsumer(type -> { if (agent.getClassHierarchy().isSuperType("java.lang.Enum", type.getName(), false)) { MethodReference toStringMethod = new MethodReference(type.getName(), "toString", ValueType.parse(String.class));