1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-11-20 02:32:36 +00:00

Used usage module to identify & remove all unneeded fragments. Many unused ones moved into a new "unused" folder to be removed later.

This commit is contained in:
jespergravgaard 2017-12-30 23:54:27 +01:00
parent aeba75906b
commit 14616458e5
155 changed files with 185 additions and 170 deletions

View File

@ -5,6 +5,7 @@ import dk.camelot64.kickc.asm.AsmProgram;
import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.CharStreams;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
@ -24,12 +25,13 @@ public class AsmFragmentManager {
/** Caches all asm fragment templates for all encountered signatures. */
private static Map<String, List<AsmFragmentTemplate>> fragmentTemplateCache = new LinkedHashMap<>();
/** Usage Statistics for fragment templates. */
private static Map<AsmFragmentTemplate, Integer> fragmentTemplateUsage = new HashMap<>();
/** Special singleton representing that the fragment can not be synthesized or loaded. */
private static AsmFragmentTemplate UNKNOWN = new AsmFragmentTemplate("UNKNOWN", null);
static Map<String, List<AsmFragmentTemplate>> getFragmentTemplateCache() {
return fragmentTemplateCache;
}
public static AsmFragment getFragment(AsmFragmentSignature signature, CompileLog log) {
AsmFragmentTemplate bestTemplate = bestFragmentCache.get(signature.getSignature());
if (bestTemplate == UNKNOWN) {
@ -39,7 +41,7 @@ public class AsmFragmentManager {
throw new UnknownFragmentException(signature.toString());
}
if (bestTemplate == null) {
AsmFragmentTemplateSynthesizer synthesizer = new AsmFragmentTemplateSynthesizer(signature, log);
AsmFragmentTemplateSynthesizer synthesizer = new AsmFragmentTemplateSynthesizer(signature.getSignature(), log);
List<AsmFragmentTemplate> candidates = synthesizer.loadOrSynthesizeFragment(signature.getSignature());
if (candidates.size() == 0) {
if (log.isVerboseFragmentLog()) {
@ -71,7 +73,7 @@ public class AsmFragmentManager {
bestFragmentCache.put(signature.getSignature(), bestTemplate);
}
// Count usages
incUsage(bestTemplate);
AsmFragmentUsages.incUsage(bestTemplate);
// Return the resulting fragment instance
return new AsmFragment(
signature.getProgram(),
@ -81,72 +83,6 @@ public class AsmFragmentManager {
signature.getBindings());
}
/**
* Count one usage of ASM fragment templates - directly or through synthesis
* @param fragmentTemplate The template to increment usage of
*/
private static void incUsage(AsmFragmentTemplate fragmentTemplate) {
Integer usage = fragmentTemplateUsage.get(fragmentTemplate);
if (usage == null) {
usage = 0;
}
fragmentTemplateUsage.put(fragmentTemplate, usage + 1);
AsmFragmentTemplate subFragment = fragmentTemplate.getSubFragment();
if (subFragment != null) {
incUsage(subFragment);
}
}
/**
* Log the usage of all template fragemnts (both loaded and synthesized).
* @param log The compile log to add the output to
*/
public static void logUsages(CompileLog log) {
ArrayList<String> signatures = new ArrayList<>(fragmentTemplateCache.keySet());
Collections.sort(signatures);
/*
log.append("ASM FRAGMENT USAGES");
for (String signature : signatures) {
List<AsmFragmentTemplate> templates = fragmentTemplateCache.get(signature);
for (AsmFragmentTemplate template : templates) {
Integer usage = fragmentTemplateUsage.get(template);
if(usage==null) usage = 0;
log.append(String.format("%8d", usage)+" "+template.getName());
}
}
*/
// Find all file fragments that were bested by a synthesized fragment
log.append("\nREDUNDANT ASM FRAGMENT FILES - REMOVE FROM DISK");
for (String signature : signatures) {
List<AsmFragmentTemplate> templates = fragmentTemplateCache.get(signature);
AsmFragmentTemplate fileTemplate = null;
int fileUsage = 0;
AsmFragmentTemplate maxTemplate = null;
int maxUsage = 0;
for (AsmFragmentTemplate template : templates) {
Integer usage = fragmentTemplateUsage.get(template);
if(usage==null) usage = 0;
if(template.isFile()) {
fileTemplate = template;
fileUsage = usage;
}
if(usage>maxUsage) {
maxUsage = usage;
maxTemplate = template;
}
}
if(fileTemplate!=null && fileUsage==0 && maxUsage>0) {
log.append("rm "+fileTemplate.getName()+".asm #synthesized by "+maxTemplate.getName()+" - usages: "+maxUsage);
}
}
}
/**
* Capable of creating fragments from signatures by loading them or synthesizing them from other smaller fragments.
* <p>
@ -155,13 +91,13 @@ public class AsmFragmentManager {
static class AsmFragmentTemplateSynthesizer {
/** Signature of the fragment being synthesized. */
private AsmFragmentSignature signature;
private String creating;
/** The log. */
private CompileLog log;
AsmFragmentTemplateSynthesizer(AsmFragmentSignature signature, CompileLog log) {
this.signature = signature;
AsmFragmentTemplateSynthesizer(String creating, CompileLog log) {
this.creating = creating;
this.log = log;
}
@ -176,7 +112,7 @@ public class AsmFragmentManager {
List<AsmFragmentTemplate> synthesized = synth.synthesize(signature, this);
if (synthesized != null) {
if (log.isVerboseFragmentLog() && synthesized.size() > 0) {
log.append("Finding fragment " + this.signature.getSignature() + " - Successfully synthesized " + synthesized.size() + " fragments " + signature + " (from " + synth.getSubSignature() + ")");
log.append("Finding fragment " + this.creating + " - Successfully synthesized " + synthesized.size() + " fragments " + signature + " (from " + synth.getSubSignature() + ")");
}
candidates.addAll(synthesized);
}
@ -184,9 +120,14 @@ public class AsmFragmentManager {
// Load the fragment from disk
CharStream fragmentCharStream = loadFragment(signature);
if (fragmentCharStream != null) {
candidates.add(new AsmFragmentTemplate(signature, fragmentCharStream.toString()));
try {
String body = fragmentCharStream.toString();
candidates.add(new AsmFragmentTemplate(signature, body));
} catch (StringIndexOutOfBoundsException e) {
throw new RuntimeException("Problem reading fragment file " + signature, e);
}
if (log.isVerboseFragmentLog()) {
log.append("Finding fragment " + this.signature.getSignature() + " - Successfully loaded fragment " + signature);
log.append("Finding fragment " + this.creating + " - Successfully loaded fragment " + signature);
}
}
fragmentTemplateCache.put(signature, candidates);
@ -215,6 +156,14 @@ public class AsmFragmentManager {
}
}
static File[] allFragmentFiles() {
ClassLoader classLoader = AsmFragmentManager.class.getClassLoader();
String path = classLoader.getResource("dk/camelot64/kickc/fragment/asm/").getPath();
return new File(path).listFiles((dir, name) -> name.endsWith(".asm"));
}
public static class UnknownFragmentException extends RuntimeException {
private String fragmentSignature;

View File

@ -0,0 +1,153 @@
package dk.camelot64.kickc.fragment;
import dk.camelot64.kickc.CompileLog;
import java.io.File;
import java.util.*;
/** Statistics for usage of the ASM fragments */
public class AsmFragmentUsages {
/** Usage Statistics for fragment templates. */
private static Map<AsmFragmentTemplate, Integer> fragmentTemplateUsage = new HashMap<>();
/**
* Count one usage of ASM fragment templates - directly or through synthesis
*
* @param fragmentTemplate The template to increment usage of
*/
static void incUsage(AsmFragmentTemplate fragmentTemplate) {
Integer usage = fragmentTemplateUsage.get(fragmentTemplate);
if (usage == null) {
usage = 0;
}
fragmentTemplateUsage.put(fragmentTemplate, usage + 1);
AsmFragmentTemplate subFragment = fragmentTemplate.getSubFragment();
if (subFragment != null) {
incUsage(subFragment);
}
}
/**
* Log the usage of all template fragemnts (both loaded and synthesized).
*
* @param log The compile log to add the output to
*/
public static void logUsages(CompileLog log, boolean logRedundantFiles, boolean logUnusedFiles, boolean logDetails) {
Map<String, List<AsmFragmentTemplate>> fragmentTemplateCache = AsmFragmentManager.getFragmentTemplateCache();
ArrayList<String> signatures = new ArrayList<>(fragmentTemplateCache.keySet());
Collections.sort(signatures);
File[] files = AsmFragmentManager.allFragmentFiles();
if (logRedundantFiles) {
// Find all file fragments that were bested by a synthesized fragment
log.append("\nREDUNDANT ASM FRAGMENT FILE ANALYSIS (if found remove them from disk)");
for (String signature : signatures) {
List<AsmFragmentTemplate> templates = fragmentTemplateCache.get(signature);
AsmFragmentTemplate fileTemplate = null;
int fileUsage = 0;
AsmFragmentTemplate maxTemplate = null;
int maxUsage = 0;
for (AsmFragmentTemplate template : templates) {
Integer usage = fragmentTemplateUsage.get(template);
if (usage == null) usage = 0;
if (template.isFile()) {
fileTemplate = template;
fileUsage = usage;
}
if (usage > maxUsage) {
maxUsage = usage;
maxTemplate = template;
}
}
if (fileTemplate != null && fileUsage == 0 && maxUsage > 0) {
log.append("rm " + fileTemplate.getName() + ".asm #synthesized by " + maxTemplate.getName() + " - usages: " + maxUsage);
}
}
log.append("\nMORE REDUNDANT ASM FRAGMENT FILE ANALYSIS (if found remove them from disk)");
Set<String> redundantSignatures = new LinkedHashSet<>();
for (File file : files) {
String fileName = file.getName();
String signature = fileName.substring(0, fileName.length() - 4);
// Try to synthesize the fragment - and check if the synthesis is as good as the file body
AsmFragmentManager.AsmFragmentTemplateSynthesizer synthesizer = new AsmFragmentManager.AsmFragmentTemplateSynthesizer(signature, log);
List<AsmFragmentTemplate> templates = synthesizer.loadOrSynthesizeFragment(signature);
AsmFragmentTemplate fileTemplate = null;
for (AsmFragmentTemplate template : templates) {
if (template.isFile()) {
fileTemplate = template;
}
}
for (AsmFragmentTemplate template : templates) {
if (!template.isFile() && template.getBody().equals(fileTemplate.getBody())) {
// Check if the synthesis uses a file marked as redundant
AsmFragmentTemplate sourceFileTemplate = template;
while (!sourceFileTemplate.isFile()) {
sourceFileTemplate = sourceFileTemplate.getSubFragment();
}
if (redundantSignatures.contains(sourceFileTemplate.getSignature())) {
throw new RuntimeException("Problem in redundancy analysis! " + sourceFileTemplate.getSignature() + ".asm seems redundant but is needed for synthesis of " + signature);
}
log.append("rm " + fileTemplate.getName() + ".asm #synthesized same ASM by " + template.getName());
redundantSignatures.add(signature);
break;
}
}
}
}
if (logUnusedFiles) {
log.append("\nUNUSED ASM FRAGMENT FILES ANALYSIS (if found consider removing them from disk)");
for (File file : files) {
String fileName = file.getName();
String signature = fileName.substring(0, fileName.length() - 4);
List<AsmFragmentTemplate> templates = fragmentTemplateCache.get(signature);
if (templates != null && templates.size() > 0) {
// The template has been loaded / synthesized - is the usage count zero?
boolean allZero = true;
Integer fileUsage = null;
for (AsmFragmentTemplate template : templates) {
Integer usage = fragmentTemplateUsage.get(template);
if (usage == null) usage = 0;
if (usage > 0) {
allZero = false;
}
if (template.isFile()) {
fileUsage = usage;
}
}
if (fileUsage == null) {
throw new RuntimeException("Error! Template file never loaded according to usage stats " + fileName);
}
if (allZero) {
log.append("git mv " + fileName + " unused # Loaded but never used");
}
} else {
// The template has never been loaded
log.append("git mv " + fileName + " unused # Never loaded");
}
}
}
if (logDetails) {
log.append("\nDETAILED ASM FRAGMENT USAGES");
for (String signature : signatures) {
List<AsmFragmentTemplate> templates = fragmentTemplateCache.get(signature);
for (AsmFragmentTemplate template : templates) {
Integer usage = fragmentTemplateUsage.get(template);
if (usage == null) usage = 0;
log.append(String.format("%8d", usage) + " " + template.getName());
}
}
}
}
}

View File

@ -1,6 +0,0 @@
clc
adc {z2}
sta {z1}
lda #0
adc {z2}+1
sta {z1}+1

View File

@ -1,7 +0,0 @@
lda #{c1}
clc
adc {z2}
sta {z1}
lda #0
adc {z2}+1
sta {z1}+1

View File

@ -1,7 +0,0 @@
txa
clc
adc {z2}
sta {z1}
lda #0
adc {z2}+1
sta {z1}+1

View File

@ -1,7 +0,0 @@
tya
clc
adc {z2}
sta {z1}
lda #0
adc {z2}+1
sta {z1}+1

View File

@ -1,7 +0,0 @@
lda {z2}
clc
adc #<{c1}
sta {z1}
lda {z2}+1
adc #>{c1}
sta {z1}+1

View File

@ -1,2 +0,0 @@
lda #{c1}
sta ({z1}),y

View File

@ -1,3 +0,0 @@
lda #{c1}
ldy {z2}
sta ({z1}),y

View File

@ -0,0 +1 @@
// do nothing

View File

@ -0,0 +1 @@
// do nothing

View File

@ -0,0 +1 @@
// do nothing

View File

@ -0,0 +1 @@
// do nothing

Some files were not shown because too many files have changed in this diff Show More