mirror of
https://gitlab.com/camelot/kickc.git
synced 2024-10-15 09:23:47 +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:
parent
aeba75906b
commit
14616458e5
@ -5,6 +5,7 @@ import dk.camelot64.kickc.asm.AsmProgram;
|
|||||||
import org.antlr.v4.runtime.CharStream;
|
import org.antlr.v4.runtime.CharStream;
|
||||||
import org.antlr.v4.runtime.CharStreams;
|
import org.antlr.v4.runtime.CharStreams;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
@ -24,12 +25,13 @@ public class AsmFragmentManager {
|
|||||||
/** Caches all asm fragment templates for all encountered signatures. */
|
/** Caches all asm fragment templates for all encountered signatures. */
|
||||||
private static Map<String, List<AsmFragmentTemplate>> fragmentTemplateCache = new LinkedHashMap<>();
|
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. */
|
/** Special singleton representing that the fragment can not be synthesized or loaded. */
|
||||||
private static AsmFragmentTemplate UNKNOWN = new AsmFragmentTemplate("UNKNOWN", null);
|
private static AsmFragmentTemplate UNKNOWN = new AsmFragmentTemplate("UNKNOWN", null);
|
||||||
|
|
||||||
|
static Map<String, List<AsmFragmentTemplate>> getFragmentTemplateCache() {
|
||||||
|
return fragmentTemplateCache;
|
||||||
|
}
|
||||||
|
|
||||||
public static AsmFragment getFragment(AsmFragmentSignature signature, CompileLog log) {
|
public static AsmFragment getFragment(AsmFragmentSignature signature, CompileLog log) {
|
||||||
AsmFragmentTemplate bestTemplate = bestFragmentCache.get(signature.getSignature());
|
AsmFragmentTemplate bestTemplate = bestFragmentCache.get(signature.getSignature());
|
||||||
if (bestTemplate == UNKNOWN) {
|
if (bestTemplate == UNKNOWN) {
|
||||||
@ -39,7 +41,7 @@ public class AsmFragmentManager {
|
|||||||
throw new UnknownFragmentException(signature.toString());
|
throw new UnknownFragmentException(signature.toString());
|
||||||
}
|
}
|
||||||
if (bestTemplate == null) {
|
if (bestTemplate == null) {
|
||||||
AsmFragmentTemplateSynthesizer synthesizer = new AsmFragmentTemplateSynthesizer(signature, log);
|
AsmFragmentTemplateSynthesizer synthesizer = new AsmFragmentTemplateSynthesizer(signature.getSignature(), log);
|
||||||
List<AsmFragmentTemplate> candidates = synthesizer.loadOrSynthesizeFragment(signature.getSignature());
|
List<AsmFragmentTemplate> candidates = synthesizer.loadOrSynthesizeFragment(signature.getSignature());
|
||||||
if (candidates.size() == 0) {
|
if (candidates.size() == 0) {
|
||||||
if (log.isVerboseFragmentLog()) {
|
if (log.isVerboseFragmentLog()) {
|
||||||
@ -71,7 +73,7 @@ public class AsmFragmentManager {
|
|||||||
bestFragmentCache.put(signature.getSignature(), bestTemplate);
|
bestFragmentCache.put(signature.getSignature(), bestTemplate);
|
||||||
}
|
}
|
||||||
// Count usages
|
// Count usages
|
||||||
incUsage(bestTemplate);
|
AsmFragmentUsages.incUsage(bestTemplate);
|
||||||
// Return the resulting fragment instance
|
// Return the resulting fragment instance
|
||||||
return new AsmFragment(
|
return new AsmFragment(
|
||||||
signature.getProgram(),
|
signature.getProgram(),
|
||||||
@ -81,72 +83,6 @@ public class AsmFragmentManager {
|
|||||||
signature.getBindings());
|
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.
|
* Capable of creating fragments from signatures by loading them or synthesizing them from other smaller fragments.
|
||||||
* <p>
|
* <p>
|
||||||
@ -155,13 +91,13 @@ public class AsmFragmentManager {
|
|||||||
static class AsmFragmentTemplateSynthesizer {
|
static class AsmFragmentTemplateSynthesizer {
|
||||||
|
|
||||||
/** Signature of the fragment being synthesized. */
|
/** Signature of the fragment being synthesized. */
|
||||||
private AsmFragmentSignature signature;
|
private String creating;
|
||||||
|
|
||||||
/** The log. */
|
/** The log. */
|
||||||
private CompileLog log;
|
private CompileLog log;
|
||||||
|
|
||||||
AsmFragmentTemplateSynthesizer(AsmFragmentSignature signature, CompileLog log) {
|
AsmFragmentTemplateSynthesizer(String creating, CompileLog log) {
|
||||||
this.signature = signature;
|
this.creating = creating;
|
||||||
this.log = log;
|
this.log = log;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -176,7 +112,7 @@ public class AsmFragmentManager {
|
|||||||
List<AsmFragmentTemplate> synthesized = synth.synthesize(signature, this);
|
List<AsmFragmentTemplate> synthesized = synth.synthesize(signature, this);
|
||||||
if (synthesized != null) {
|
if (synthesized != null) {
|
||||||
if (log.isVerboseFragmentLog() && synthesized.size() > 0) {
|
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);
|
candidates.addAll(synthesized);
|
||||||
}
|
}
|
||||||
@ -184,9 +120,14 @@ public class AsmFragmentManager {
|
|||||||
// Load the fragment from disk
|
// Load the fragment from disk
|
||||||
CharStream fragmentCharStream = loadFragment(signature);
|
CharStream fragmentCharStream = loadFragment(signature);
|
||||||
if (fragmentCharStream != null) {
|
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()) {
|
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);
|
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 {
|
public static class UnknownFragmentException extends RuntimeException {
|
||||||
|
|
||||||
private String fragmentSignature;
|
private String fragmentSignature;
|
||||||
|
153
src/main/java/dk/camelot64/kickc/fragment/AsmFragmentUsages.java
Normal file
153
src/main/java/dk/camelot64/kickc/fragment/AsmFragmentUsages.java
Normal 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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -1,6 +0,0 @@
|
|||||||
clc
|
|
||||||
adc {z2}
|
|
||||||
sta {z1}
|
|
||||||
lda #0
|
|
||||||
adc {z2}+1
|
|
||||||
sta {z1}+1
|
|
@ -1,7 +0,0 @@
|
|||||||
lda #{c1}
|
|
||||||
clc
|
|
||||||
adc {z2}
|
|
||||||
sta {z1}
|
|
||||||
lda #0
|
|
||||||
adc {z2}+1
|
|
||||||
sta {z1}+1
|
|
@ -1,7 +0,0 @@
|
|||||||
txa
|
|
||||||
clc
|
|
||||||
adc {z2}
|
|
||||||
sta {z1}
|
|
||||||
lda #0
|
|
||||||
adc {z2}+1
|
|
||||||
sta {z1}+1
|
|
@ -1,7 +0,0 @@
|
|||||||
tya
|
|
||||||
clc
|
|
||||||
adc {z2}
|
|
||||||
sta {z1}
|
|
||||||
lda #0
|
|
||||||
adc {z2}+1
|
|
||||||
sta {z1}+1
|
|
@ -1,7 +0,0 @@
|
|||||||
lda {z2}
|
|
||||||
clc
|
|
||||||
adc #<{c1}
|
|
||||||
sta {z1}
|
|
||||||
lda {z2}+1
|
|
||||||
adc #>{c1}
|
|
||||||
sta {z1}+1
|
|
@ -1,2 +0,0 @@
|
|||||||
lda #{c1}
|
|
||||||
sta ({z1}),y
|
|
@ -1,2 +0,0 @@
|
|||||||
txa
|
|
||||||
sta ({z1}),y
|
|
@ -1,3 +0,0 @@
|
|||||||
lda #{c1}
|
|
||||||
ldy {z2}
|
|
||||||
sta ({z1}),y
|
|
@ -0,0 +1 @@
|
|||||||
|
// do nothing
|
@ -0,0 +1 @@
|
|||||||
|
// do nothing
|
@ -0,0 +1 @@
|
|||||||
|
// do nothing
|
@ -0,0 +1 @@
|
|||||||
|
// do nothing
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user