public RegularMethodNode read(DataInput input, MethodReference method) throws IOException { RegularMethodNode node = new RegularMethodNode(method); node.getModifiers().addAll(unpackModifiers(input.readInt())); int varCount = input.readShort(); for (int i = 0; i < varCount; ++i) { node.getVariables().add(readVariable(input)); } node.setBody(readStatement(input)); return node; }
public void optimize(RegularMethodNode method, Program program, boolean friendlyToDebugger) { ReadWriteStatsBuilder stats = new ReadWriteStatsBuilder(method.getVariables().size()); stats.analyze(program); applyParametersToWriteStats(stats, method.getReference()); boolean[] preservedVars = new boolean[stats.writes.length]; BreakEliminator breakEliminator = new BreakEliminator(); breakEliminator.eliminate(method.getBody()); if (friendlyToDebugger) { for (int i = 0; i < method.getVariables().size(); ++i) { if (method.getVariables().get(i).getName() != null) { preservedVars[i] = true; } } } OptimizingVisitor optimizer = new OptimizingVisitor(preservedVars, stats.writes, stats.reads, moveConstants ? stats.constants : new Object[stats.constants.length], friendlyToDebugger); method.getBody().acceptVisitor(optimizer); method.setBody(optimizer.resultStmt); int paramCount = method.getReference().parameterCount(); UnusedVariableEliminator unusedEliminator = new UnusedVariableEliminator(paramCount, method.getVariables()); method.getBody().acceptVisitor(unusedEliminator); method.getVariables().clear(); method.getVariables().addAll(unusedEliminator.getReorderedVariables()); method.getBody().acceptVisitor(new RedundantLabelEliminator()); method.getBody().acceptVisitor(new RedundantReturnElimination()); for (int i = 0; i < method.getVariables().size(); ++i) { method.getVariables().get(i).setIndex(i); } }
public void write(DataOutput output, RegularMethodNode method) throws IOException { output.writeInt(ElementModifier.pack(method.getModifiers())); output.writeShort(method.getVariables().size()); for (VariableNode var : method.getVariables()) { write(output, var); } try { method.getBody().acceptVisitor(new NodeWriter(output)); } catch (IOExceptionWrapper e) { throw new IOException("Error writing method body", e.getCause()); } }
statementRenderer.setAsync(false); this.async = false; MethodReference ref = method.getReference(); for (int i = 0; i < method.getVariables().size(); ++i) { debugEmitter.emitVariable(new String[] { method.getVariables().get(i).getName() }, statementRenderer.variableName(i)); for (VariableNode var : method.getVariables()) { variableCount = Math.max(variableCount, var.getIndex() + 1); method.getBody().acceptVisitor(tryCatchFinder); boolean hasTryCatch = tryCatchFinder.tryCatchFound; List<String> variableNames = new ArrayList<>(); statementRenderer.setCurrentPart(0); if (method.getModifiers().contains(ElementModifier.SYNCHRONIZED)) { writer.appendMethodBody(NameFrequencyEstimator.MONITOR_ENTER_SYNC_METHOD); writer.append("("); method.getBody().acceptVisitor(statementRenderer); if (method.getModifiers().contains(ElementModifier.SYNCHRONIZED)) { writer.outdent().append("}").ws().append("finally").ws().append("{").indent().softNewLine();
public void generateMethod(RegularMethodNode methodNode) { generateMethodSignature(writer, methodNode.getReference(), methodNode.getModifiers().contains(ElementModifier.STATIC), true); writer.print(" {").indent().println(); localsWriter = writer.fragment(); CodeGenerationVisitor visitor = new CodeGenerationVisitor(context, writer, includes); visitor.setCallingMethod(methodNode.getReference()); methodNode.getBody().acceptVisitor(visitor); generateLocals(methodNode, visitor.getTemporaries()); writer.outdent().println("}"); }
statementRenderer.setAsync(false); this.async = false; MethodReference ref = method.getReference(); for (int i = 0; i < method.getVariables().size(); ++i) { debugEmitter.emitVariable(new String[] { method.getVariables().get(i).getName() }, statementRenderer.variableName(i)); for (VariableNode var : method.getVariables()) { variableCount = Math.max(variableCount, var.getIndex() + 1); method.getBody().acceptVisitor(tryCatchFinder); boolean hasTryCatch = tryCatchFinder.tryCatchFound; List<String> variableNames = new ArrayList<>(); method.getBody().acceptVisitor(statementRenderer); } catch (IOException e) { throw new RenderingException("IO error occurred", e);
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; }
private void generateLocals(RegularMethodNode methodNode, int[] temporaryCount) { int start = methodNode.getReference().parameterCount() + 1; for (int i = start; i < methodNode.getVariables().size(); ++i) { VariableNode variableNode = methodNode.getVariables().get(i); if (variableNode.getType() == null) { continue; } localsWriter.printType(variableNode.getType()).print(" local_").print(String.valueOf(i)).println(";"); } for (CVariableType type : CVariableType.values()) { for (int i = 0; i < temporaryCount[type.ordinal()]; ++i) { localsWriter.print(type.text + " tmp_" + type.name().toLowerCase() + "_" + i).println(";"); } } } }
@Override public void visit(RegularMethodNode methodNode) { async = false; methodNode.getBody().acceptVisitor(this); }
public void write(DataOutput output, RegularMethodNode method) throws IOException { output.writeInt(packModifiers(method.getModifiers())); output.writeShort(method.getVariables().size()); for (VariableNode var : method.getVariables()) { write(output, var); } try { method.getBody().acceptVisitor(new NodeWriter(output)); } catch (IOExceptionWrapper e) { throw new IOException("Error writing method body", e.getCause()); } }
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(WasmMangling.mangleMethod(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 String[] extract(RegularMethodNode node) { node.getBody().acceptVisitor(visitor); String[] result = visitor.dependencies.toArray(new String[0]); visitor.dependencies.clear(); return result; }
public RegularMethodNode decompileRegularCacheMiss(MethodHolder method) { RegularMethodNode methodNode = new RegularMethodNode(method.getReference()); Program program = method.getProgram(); int[] targetBlocks = new int[program.basicBlockCount()]; Arrays.fill(targetBlocks, -1); try { methodNode.setBody(getRegularMethodStatement(program, targetBlocks, false).getStatement()); } catch (RuntimeException e) { StringBuilder sb = new StringBuilder("Error decompiling method " + method.getReference() + ":\n"); sb.append(new ListingBuilder().buildListing(program, " ")); throw new DecompilationException(sb.toString(), e); } TypeInferer typeInferer = new TypeInferer(); typeInferer.inferTypes(program, method.getReference()); for (int i = 0; i < program.variableCount(); ++i) { VariableNode variable = new VariableNode(program.variableAt(i).getRegister(), typeInferer.typeOf(i)); variable.setName(program.variableAt(i).getDebugName()); methodNode.getVariables().add(variable); } Optimizer optimizer = new Optimizer(moveConstants); optimizer.optimize(methodNode, method.getProgram(), friendlyToDebugger); methodNode.getModifiers().addAll(method.getModifiers()); return methodNode; }
public void optimize(RegularMethodNode method, Program program, boolean friendlyToDebugger) { ReadWriteStatsBuilder stats = new ReadWriteStatsBuilder(method.getVariables().size()); stats.analyze(program); boolean[] preservedVars = new boolean[stats.writes.length]; BreakEliminator breakEliminator = new BreakEliminator(); breakEliminator.eliminate(method.getBody()); OptimizingVisitor optimizer = new OptimizingVisitor(preservedVars, stats.writes, stats.reads, friendlyToDebugger); method.getBody().acceptVisitor(optimizer); method.setBody(optimizer.resultStmt); int paramCount = method.getReference().parameterCount(); UnusedVariableEliminator unusedEliminator = new UnusedVariableEliminator(paramCount, method.getVariables()); method.getBody().acceptVisitor(unusedEliminator); method.getVariables().clear(); method.getVariables().addAll(unusedEliminator.getReorderedVariables()); method.getBody().acceptVisitor(new RedundantLabelEliminator()); method.getBody().acceptVisitor(new RedundantReturnElimination()); for (int i = 0; i < method.getVariables().size(); ++i) { method.getVariables().get(i).setIndex(i); } }
@Override public void visit(RegularMethodNode methodNode) { async = false; methodNode.getBody().acceptVisitor(this); }
public RegularMethodNode read(DataInput input, MethodReference method) throws IOException { RegularMethodNode node = new RegularMethodNode(method); node.getModifiers().addAll(unpackModifiers(input.readInt())); int varCount = input.readShort(); for (int i = 0; i < varCount; ++i) { node.getVariables().add(readVariable(input)); } node.setBody(readStatement(input)); return node; }
AstDependencyAnalyzer analyzer = new AstDependencyAnalyzer(); RegularMethodNode node = cache.get(method).node; node.getBody().acceptVisitor(analyzer); analyzer.dependencies.add(method.getClassName()); try (DataOutputStream output = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(file)))) {
public RegularMethodNode decompileRegularCacheMiss(MethodHolder method) { RegularMethodNode methodNode = new RegularMethodNode(method.getReference()); Program program = method.getProgram(); int[] targetBlocks = new int[program.basicBlockCount()]; Arrays.fill(targetBlocks, -1); try { methodNode.setBody(getRegularMethodStatement(program, targetBlocks, false).getStatement()); } catch (RuntimeException e) { StringBuilder sb = new StringBuilder("Error decompiling method " + method.getReference() + ":\n"); sb.append(new ListingBuilder().buildListing(program, " ")); throw new DecompilationException(sb.toString(), e); } TypeInferer typeInferer = new TypeInferer(); typeInferer.inferTypes(program, method.getReference()); for (int i = 0; i < program.variableCount(); ++i) { VariableNode variable = new VariableNode(program.variableAt(i).getRegister(), typeInferer.typeOf(i)); variable.setName(program.variableAt(i).getDebugName()); methodNode.getVariables().add(variable); } Optimizer optimizer = new Optimizer(); optimizer.optimize(methodNode, method.getProgram(), friendlyToDebugger); methodNode.getModifiers().addAll(method.getModifiers()); return methodNode; }