Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -178,10 +178,10 @@ public void addWritableField(String field) {
/**
* Marks dependencies in this class based on the provided classes in this round of optimization.
* @param lst The list of classes that are available in this optimization step.
* @param nativeSources Array of native sources in this round. Used to check if native files reference
* @param nativeTokens Set of native tokens in this round. Used to check if native files reference
* this class or methods.
*/
public static void markDependencies(List<ByteCodeClass> lst, String[] nativeSources) {
public static void markDependencies(List<ByteCodeClass> lst, Set<String> nativeTokens) {
mainClass.markDependent(lst);
for(ByteCodeClass bc : lst) {
if (bc.marked) {
Expand Down Expand Up @@ -237,7 +237,7 @@ public static void markDependencies(List<ByteCodeClass> lst, String[] nativeSour
if (bc.getUsedByNative() == UsedByNativeResult.Unknown) {
// We don't yet know if this class is used by native
// calculate it now.
bc.calcUsedByNative(nativeSources);
bc.calcUsedByNative(nativeTokens);
}
if(bc.getUsedByNative() == UsedByNativeResult.Used){
bc.markDependent(lst);
Expand Down Expand Up @@ -1818,18 +1818,30 @@ public UsedByNativeResult getUsedByNative() {
return usedByNative;
}

public void resolveNativeUsage(Set<String> nativeTokens) {
if (usedByNative != UsedByNativeResult.Unknown) return;
for(String token : nativeTokens) {
if(token.contains(clsName)) {
setUsedByNative(true);
return;
}
}
setUsedByNative(false);
}

/**
* Calculates whether this class is used in any of the native sources.
* @param nativeSources The native sources to check.
* @param nativeTokens The native sources to check.
* @see #getUsedByNative()
* @see #setUsedByNative(boolean)
*/
public void calcUsedByNative(String[] nativeSources) {
public void calcUsedByNative(Set<String> nativeTokens) {
resolveNativeUsage(nativeTokens);
if (usedByNative == UsedByNativeResult.Unused) {
return;
}
for (BytecodeMethod m : methods) {
if (usedByNative != UsedByNativeResult.Unknown) {
return;
}
m.isMethodUsedByNative(nativeSources, this);
m.isMethodUsedByNative(nativeTokens, this);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -294,28 +294,33 @@ public boolean isMethodUsed(BytecodeMethod bm0) {
* Internal use: to track the list of native sources that were used to calculate the
* usedByNative flag.
*/
private String[] usedByNativeSources;
private Set<String> usedByNativeSources;

/**
* Checks to see if this method is used by any of the provided native sources.
* @param nativeSources The native sources to check.
* @param nativeTokens The native sources to check.
* @param cls The class that the method belongs to. This is used to improve performance by first checking to
* see if the class is Not referenced in native sources. If the class is not referenced, then we know that
* neither is the method. This method will also set the {@link ByteCodeClass#setUsedByNative(boolean)} flag
* to improve the performance for the next method that is checked in the same class.
* @return True if the method is used by native.
*/
public boolean isMethodUsedByNative(String[] nativeSources, ByteCodeClass cls) {
if (nativeSources == null) return false;
if (nativeSources == usedByNativeSources) {
public boolean isMethodUsedByNative(Set<String> nativeTokens, ByteCodeClass cls) {
if (nativeTokens == null) return false;
if (nativeTokens == usedByNativeSources) {
return usedByNative;
}
usedByNativeSources = nativeSources;
usedByNativeSources = nativeTokens;

if (cls != null && cls.getUsedByNative() == ByteCodeClass.UsedByNativeResult.Unused) {
// If the class isn't used, then neither is the method.
usedByNative = false;
return false;
if (cls != null) {
if (cls.getUsedByNative() == ByteCodeClass.UsedByNativeResult.Unknown) {
cls.resolveNativeUsage(nativeTokens);
}
if (cls.getUsedByNative() == ByteCodeClass.UsedByNativeResult.Unused) {
// If the class isn't used, then neither is the method.
usedByNative = false;
return false;
}
}


Expand All @@ -324,26 +329,15 @@ public boolean isMethodUsedByNative(String[] nativeSources, ByteCodeClass cls) {
StringBuilder b = new StringBuilder();
this.appendFunctionPointer(b);
String str = b.toString();
boolean foundClassName = false;
for(String s : nativeSources) {
if (cls != null && !foundClassName && s.contains(clsName)) {
// For later we record whether the class is used.
foundClassName = true;
}
if(s.contains(str)) {
usedByNative = true;
if (cls != null) {
cls.setUsedByNative(true);
}
return true;
}
}
if (!foundClassName && cls != null) {
// We didn't find the class at all.
// Let's record that as it will save us time
// when looking up other methods in this class.
cls.setUsedByNative(false);

if (nativeTokens.contains(str)) {
usedByNative = true;
if (cls != null) {
cls.setUsedByNative(true);
}
return true;
}

usedByNative = false;
return false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,11 @@
public class Parser extends ClassVisitor {
private ByteCodeClass cls;
private String clsName;
private static String[] nativeSources;
private static Set<String> nativeTokens;
private static List<ByteCodeClass> classes = new ArrayList<ByteCodeClass>();
private int lambdaCounter;
public static void cleanup() {
nativeSources = null;
nativeTokens = null;
classes.clear();
LabelInstruction.cleanup();
}
Expand Down Expand Up @@ -420,7 +420,7 @@ public static void writeOutput(File outputDirectory) throws Exception {
file = bc.getClsName();
bc.updateAllDependencies();
}
ByteCodeClass.markDependencies(classes, nativeSources);
ByteCodeClass.markDependencies(classes, nativeTokens);
Set<ByteCodeClass> unmarked = new HashSet<ByteCodeClass>(classes);
classes = ByteCodeClass.clearUnmarked(classes);
unmarked.removeAll(classes);
Expand Down Expand Up @@ -471,7 +471,7 @@ public boolean accept(File file) {
return file.getName().endsWith(".m") || file.getName().endsWith("." + ByteCodeTranslator.output.extension());
}
});
nativeSources = new String[mFiles.length];
nativeTokens = new HashSet<String>();
int size = 0;
System.out.println(""+mFiles.length +" native files");
for(int iter = 0 ; iter < mFiles.length ; iter++) {
Expand All @@ -482,7 +482,15 @@ public boolean accept(File file) {
byte[] dat = new byte[len];
di.readFully(dat);
fi.close();
nativeSources[iter] = new String(dat, "UTF-8");
String s = new String(dat, "UTF-8");

// tokenize the file content
String[] tokens = s.split("[^a-zA-Z0-9_$]+");
for(String t : tokens) {
if(t.length() > 1) {
nativeTokens.add(t);
}
}
}
System.out.println("Native files total "+(size/1024)+"K");

Expand Down Expand Up @@ -577,7 +585,7 @@ private static int cullClasses(boolean found, int depth) {
bc.updateAllDependencies();
}

ByteCodeClass.markDependencies(classes, nativeSources);
ByteCodeClass.markDependencies(classes, nativeTokens);
List<ByteCodeClass> tmp = ByteCodeClass.clearUnmarked(classes);
/*if(ByteCodeTranslator.verbose) {
System.out.println("Classes removed from: " + classCount + " to " + classes.size());
Expand Down Expand Up @@ -610,7 +618,7 @@ private static int cullClasses(boolean found, int depth) {


private static boolean isMethodUsed(BytecodeMethod m, ByteCodeClass cls) {
if (!m.isEliminated() && m.isMethodUsedByNative(nativeSources, cls)) {
if (!m.isEliminated() && m.isMethodUsedByNative(nativeTokens, cls)) {
return true;
}
for(ByteCodeClass bc : classes) {
Expand Down
Loading