static void makeSync(MethodHolder method) { if (method.getAnnotations().get(Sync.class.getName()) == null) { AnnotationHolder annot = new AnnotationHolder(Sync.class.getName()); method.getAnnotations().add(annot); } }
@Override public void transformClass(ClassHolder cls, ClassHolderTransformerContext context) { for (MethodHolder method : cls.getMethods()) { AnnotationReader delegateAnnot = method.getAnnotations().get(DelegateTo.class.getName()); if (delegateAnnot != null) { method.setProgram(null); method.getModifiers().add(ElementModifier.NATIVE); } } } }
@Override public void transformClass(ClassHolder cls, ClassHolderTransformerContext context) { for (MethodHolder method : cls.getMethods()) { AnnotationReader delegateAnnot = method.getAnnotations().get(DelegateTo.class.getName()); if (delegateAnnot != null) { method.setProgram(null); method.getModifiers().add(ElementModifier.NATIVE); } } } }
@Override public void transformClass(ClassHolder cls, ClassHolderTransformerContext context) { for (MethodHolder method : cls.getMethods()) { if (method.getAnnotations().get(JavaScriptBody.class.getName()) != null) { AnnotationHolder genAnnot = new AnnotationHolder(GeneratedBy.class.getName()); genAnnot.getValues().put("value", new AnnotationValue(ValueType.object( JavaScriptBodyGenerator.class.getName()))); method.getAnnotations().add(genAnnot); method.setProgram(null); method.getModifiers().add(ElementModifier.NATIVE); } } } }
void createJSMethods(ClassHolder cls) { for (MethodHolder method : cls.getMethods().toArray(new MethodHolder[0])) { MethodReference methodRef = method.getReference(); if (method.getAnnotations().get(JSBody.class.getName()) == null) { continue; } requireJSBody(diagnostics, method); if (!repository.methodMap.containsKey(method.getReference())) { continue; } MethodReference proxyRef = repository.methodMap.get(methodRef); MethodHolder proxyMethod = new MethodHolder(proxyRef.getDescriptor()); proxyMethod.getModifiers().add(ElementModifier.NATIVE); proxyMethod.getModifiers().add(ElementModifier.STATIC); boolean inline = repository.inlineMethods.contains(methodRef); AnnotationHolder generatorAnnot = new AnnotationHolder(inline ? DynamicInjector.class.getName() : DynamicGenerator.class.getName()); proxyMethod.getAnnotations().add(generatorAnnot); cls.addMethod(proxyMethod); Set<MethodReference> callbacks = repository.callbackMethods.get(proxyRef); if (callbacks != null) { for (MethodReference callback : callbacks) { generateCallbackCaller(cls, callback); } } } }
private boolean validate(MethodHolder method, Diagnostics diagnostics) { AnnotationReader providerAnnot = method.getAnnotations().get(MetadataProvider.class.getName()); if (providerAnnot == null) { return false; } if (!method.hasModifier(ElementModifier.NATIVE)) { diagnostics.error(new CallLocation(method.getReference()), "Method {{m0}} is marked with " + "{{c1}} annotation, but it is not native", method.getReference(), MetadataProvider.class.getName()); return false; } return true; } }
private String[] getExpectedExceptions(MethodHolder method) { AnnotationHolder annot = method.getAnnotations().get(JUNIT4_TEST); if (annot == null) { return new String[0]; } AnnotationValue expected = annot.getValue("expected"); if (expected == null) { return new String[0]; } ValueType result = expected.getJavaClass(); return new String[] { ((ValueType.Object) result).getClassName() }; }
@Override public void transformClass(ClassHolder cls, ClassHolderTransformerContext context) { int index = 0; for (MethodHolder method : cls.getMethods().toArray(new MethodHolder[0])) { AnnotationReader providerAnnot = method.getAnnotations().get(MetadataProvider.class.getName()); if (providerAnnot != null) { transformMetadataMethod(cls, method, context.getDiagnostics(), context.getHierarchy(), index++); } providerAnnot = method.getAnnotations().get(ClassScopedMetadataProvider.class.getName()); if (providerAnnot != null) { ValueType[] params = method.getParameterTypes(); if (params.length != 1 && params[0].isObject(PlatformClass.class.getName())) { context.getDiagnostics().error(new CallLocation(method.getReference()), "Method {{m0}} marked with {{c1}} must take exactly one parameter of type {{c2}}", method.getReference(), ClassScopedMetadataProvider.class.getName(), PlatformClass.class.getName()); } AnnotationHolder genAnnot = new AnnotationHolder(GeneratedBy.class.getName()); genAnnot.getValues().put("value", new AnnotationValue(ValueType.object( ClassScopedMetadataProviderNativeGenerator.class.getName()))); method.getAnnotations().add(genAnnot); } } }
private boolean tryDelegateToMethod(ClassHolder cls, MethodHolder method) { AnnotationHolder delegateToAnnot = method.getAnnotations().get(DelegateTo.class.getName()); if (delegateToAnnot == null) { return false; } String methodName = delegateToAnnot.getValue("value").getString(); for (MethodHolder candidate : cls.getMethods()) { if (candidate.getName().equals(methodName)) { generateMethodForwardDeclaration(method); delegateToMethod(method, candidate); return true; } } return false; }
private MethodHolder readMethod(InputStream stream) throws IOException { DataInputStream input = new DataInputStream(stream); MethodHolder method = new MethodHolder(MethodDescriptor.parse(symbolTable.at(input.readInt()))); method.setLevel(accessLevels[input.readByte()]); method.getModifiers().addAll(unpackModifiers(input.readInt())); readAnnotations(input, method.getAnnotations()); for (int i = 0; i < method.parameterCount(); ++i) { readAnnotations(input, method.parameterAnnotation(i)); } if (input.readBoolean()) { method.setAnnotationDefault(readAnnotationValue(input)); } boolean hasProgram = input.readBoolean(); if (hasProgram) { method.setProgram(programIO.read(input)); } return method; }
public MethodHolder rename(MethodHolder method) { String methodName = method.getName(); AnnotationHolder renameAnnot = method.getAnnotations().get(Rename.class.getName()); if (renameAnnot != null) { methodName = renameAnnot.getValues().get("value").getString(); } ValueType[] signature = method.getSignature(); for (int i = 0; i < signature.length; ++i) { signature[i] = rename(signature[i]); } MethodHolder renamedMethod = new MethodHolder(methodName, signature); renamedMethod.getModifiers().addAll(method.getModifiers()); renamedMethod.setLevel(method.getLevel()); renamedMethod.setProgram(method.getProgram()); rename(method.getAnnotations(), renamedMethod.getAnnotations()); rename(renamedMethod.getProgram()); return renamedMethod; }
private void writeMethod(OutputStream stream, MethodHolder method) throws IOException { DataOutputStream output = new DataOutputStream(stream); output.writeInt(symbolTable.lookup(method.getDescriptor().toString())); output.writeByte(method.getLevel().ordinal()); output.writeInt(packModifiers(method.getModifiers())); writeAnnotations(output, method.getAnnotations()); for (AnnotationContainer parameterAnnotation : method.getParameterAnnotations()) { writeAnnotations(output, parameterAnnotation); } if (method.getAnnotationDefault() != null) { output.writeBoolean(true); writeAnnotationValue(output, method.getAnnotationDefault()); } else { output.writeBoolean(false); } if (method.getProgram() != null) { output.writeBoolean(true); programIO.write(method.getProgram(), output); } else { output.writeBoolean(false); } }
public NativeMethodNode decompileNative(MethodHolder method) { Generator generator = generators.get(method.getReference()); if (generator == null && !isBootstrap()) { AnnotationHolder annotHolder = method.getAnnotations().get(GeneratedBy.class.getName()); if (annotHolder == null) { throw new DecompilationException("Method " + method.getOwnerName() + "." + method.getDescriptor() + " is native, but no " + GeneratedBy.class.getName() + " annotation found"); } ValueType annotValue = annotHolder.getValues().get("value").getJavaClass(); String generatorClassName = ((ValueType.Object) annotValue).getClassName(); try { Class<?> generatorClass = Class.forName(generatorClassName, true, classLoader); generator = (Generator) generatorClass.newInstance(); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) { throw new DecompilationException("Error instantiating generator " + generatorClassName + " for native method " + method.getOwnerName() + "." + method.getDescriptor()); } } NativeMethodNode methodNode = new NativeMethodNode(method.getReference()); methodNode.getModifiers().addAll(method.getModifiers()); methodNode.setGenerator(generator); methodNode.setAsync(asyncMethods.contains(method.getReference())); return methodNode; }
public ClassNode decompile(ClassHolder cls) { ClassNode clsNode = new ClassNode(cls.getName(), cls.getParent()); for (FieldHolder field : cls.getFields()) { FieldNode fieldNode = new FieldNode(field.getReference(), field.getType()); fieldNode.getModifiers().addAll(field.getModifiers()); fieldNode.setInitialValue(field.getInitialValue()); clsNode.getFields().add(fieldNode); } for (MethodHolder method : cls.getMethods()) { if (method.getModifiers().contains(ElementModifier.ABSTRACT)) { continue; } if ((!isBootstrap() && method.getAnnotations().get(InjectedBy.class.getName()) != null) || methodsToSkip.contains(method.getReference())) { continue; } MethodNode methodNode = decompile(method); clsNode.getMethods().add(methodNode); } clsNode.getInterfaces().addAll(cls.getInterfaces()); clsNode.getModifiers().addAll(cls.getModifiers()); clsNode.setAccessLevel(cls.getLevel()); return clsNode; }
genAnnot.getValues().put("value", new AnnotationValue(ValueType.object( MetadataProviderNativeGenerator.class.getName()))); createMethod.getAnnotations().add(genAnnot); ModelUtils.copyAnnotations(method.getAnnotations(), createMethod.getAnnotations()); createMethod.getAnnotations().add(refAnnot);
@Override public void transformClass(ClassHolder cls, ClassHolderTransformerContext context) { for (MethodHolder method : cls.getMethods()) { if (method.hasModifier(ElementModifier.NATIVE) && method.getAnnotations().get(Async.class.getName()) != null && method.getAnnotations().get(GeneratedBy.class.getName()) == null) { ValueType[] signature = new ValueType[method.parameterCount() + 2]; for (int i = 0; i < method.parameterCount(); ++i) { signature[i] = method.parameterType(i); } signature[method.parameterCount()] = ValueType.parse(AsyncCallback.class); signature[method.parameterCount() + 1] = ValueType.VOID; MethodDescriptor asyncDesc = new MethodDescriptor(method.getName(), signature); MethodHolder asyncMethod = cls.getMethod(asyncDesc); if (asyncMethod != null) { if (asyncMethod.hasModifier(ElementModifier.STATIC) != method.hasModifier(ElementModifier.STATIC)) { context.getDiagnostics().error(new CallLocation(method.getReference()), "Methods {{m0}} and {{m1}} must both be either static or non-static", method.getReference(), asyncMethod.getReference()); } } } } } }
public WasmFunction generate(MethodReference methodReference, MethodHolder bodyMethod) { ClassHolder cls = classSource.get(methodReference.getClassName()); MethodHolder method = cls.getMethod(methodReference.getDescriptor()); RegularMethodNode methodAst = decompiler.decompileRegular(bodyMethod); WasmFunction function = context.getFunction(names.forMethod(methodReference)); int firstVariable = method.hasModifier(ElementModifier.STATIC) ? 1 : 0; for (int i = firstVariable; i < methodAst.getVariables().size(); ++i) { VariableNode variable = methodAst.getVariables().get(i); WasmType type = variable.getType() != null ? WasmGeneratorUtil.mapType(variable.getType()) : WasmType.INT32; function.add(new WasmLocal(type, variable.getName())); } WasmGenerationVisitor visitor = new WasmGenerationVisitor(context, classGenerator, binaryWriter, function, firstVariable); methodAst.getBody().acceptVisitor(visitor); if (visitor.result instanceof WasmBlock) { ((WasmBlock) visitor.result).setType(function.getResult()); } function.getBody().add(visitor.result); AnnotationReader exportAnnot = method.getAnnotations().get(Export.class.getName()); if (exportAnnot != null) { function.setExportName(exportAnnot.getValue("name").getString()); } return function; }
public static MethodHolder copyMethod(MethodReader method, boolean withProgram) { MethodHolder copy = new MethodHolder(method.getDescriptor()); copy.setLevel(method.getLevel()); copy.getModifiers().addAll(method.readModifiers()); if (method.getProgram() != null && withProgram) { copy.setProgram(ProgramUtils.copy(method.getProgram())); } copyAnnotations(method.getAnnotations(), copy.getAnnotations()); if (method.getAnnotationDefault() != null) { copy.setAnnotationDefault(copyAnnotationValue(method.getAnnotationDefault())); } for (int i = 0; i < method.parameterCount(); ++i) { copyAnnotations(method.parameterAnnotation(i), copy.parameterAnnotation(i)); } return copy; }
void processMemberMethods(ClassHolder cls) { for (MethodHolder method : cls.getMethods().toArray(new MethodHolder[0])) { if (method.hasModifier(ElementModifier.STATIC)) { continue; } if (method.getProgram() != null && method.getProgram().basicBlockCount() > 0) { ValueType[] staticSignature = getStaticSignature(method.getReference()); MethodHolder callerMethod = new MethodHolder(new MethodDescriptor(method.getName() + "$static", staticSignature)); callerMethod.getModifiers().add(ElementModifier.STATIC); Program program = ProgramUtils.copy(method.getProgram()); program.createVariable(); InstructionVariableMapper variableMapper = new InstructionVariableMapper(var -> program.variableAt(var.getIndex() + 1)); for (int i = program.variableCount() - 1; i > 0; --i) { program.variableAt(i).setDebugName(program.variableAt(i - 1).getDebugName()); program.variableAt(i).setLabel(program.variableAt(i - 1).getLabel()); } for (int i = 0; i < program.basicBlockCount(); ++i) { BasicBlock block = program.basicBlockAt(i); variableMapper.apply(block); } callerMethod.setProgram(program); ModelUtils.copyAnnotations(method.getAnnotations(), callerMethod.getAnnotations()); cls.addMethod(callerMethod); } } }
applyDebugNames(program, phiUpdater, programParser, argumentMapping); parseAnnotations(method.getAnnotations(), node.visibleAnnotations, node.invisibleAnnotations); applyDebugNames(program, phiUpdater, programParser, applySignature(program, method.getDescriptor().getParameterTypes()));