diff --git a/vm/ByteCodeTranslator/src/com/codename1/tools/translator/ByteCodeClass.java b/vm/ByteCodeTranslator/src/com/codename1/tools/translator/ByteCodeClass.java index c61ea2193f..cca57814e2 100644 --- a/vm/ByteCodeTranslator/src/com/codename1/tools/translator/ByteCodeClass.java +++ b/vm/ByteCodeTranslator/src/com/codename1/tools/translator/ByteCodeClass.java @@ -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 lst, String[] nativeSources) { + public static void markDependencies(List lst, Set nativeTokens) { mainClass.markDependent(lst); for(ByteCodeClass bc : lst) { if (bc.marked) { @@ -237,7 +237,7 @@ public static void markDependencies(List 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); @@ -1818,18 +1818,30 @@ public UsedByNativeResult getUsedByNative() { return usedByNative; } + public void resolveNativeUsage(Set 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 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); } } diff --git a/vm/ByteCodeTranslator/src/com/codename1/tools/translator/BytecodeMethod.java b/vm/ByteCodeTranslator/src/com/codename1/tools/translator/BytecodeMethod.java index ff008acd94..3955d3c56f 100644 --- a/vm/ByteCodeTranslator/src/com/codename1/tools/translator/BytecodeMethod.java +++ b/vm/ByteCodeTranslator/src/com/codename1/tools/translator/BytecodeMethod.java @@ -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 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 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; + } } @@ -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; } diff --git a/vm/ByteCodeTranslator/src/com/codename1/tools/translator/Parser.java b/vm/ByteCodeTranslator/src/com/codename1/tools/translator/Parser.java index dbc8d9f510..b959be5c75 100644 --- a/vm/ByteCodeTranslator/src/com/codename1/tools/translator/Parser.java +++ b/vm/ByteCodeTranslator/src/com/codename1/tools/translator/Parser.java @@ -48,11 +48,11 @@ public class Parser extends ClassVisitor { private ByteCodeClass cls; private String clsName; - private static String[] nativeSources; + private static Set nativeTokens; private static List classes = new ArrayList(); private int lambdaCounter; public static void cleanup() { - nativeSources = null; + nativeTokens = null; classes.clear(); LabelInstruction.cleanup(); } @@ -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 unmarked = new HashSet(classes); classes = ByteCodeClass.clearUnmarked(classes); unmarked.removeAll(classes); @@ -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(); int size = 0; System.out.println(""+mFiles.length +" native files"); for(int iter = 0 ; iter < mFiles.length ; iter++) { @@ -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"); @@ -577,7 +585,7 @@ private static int cullClasses(boolean found, int depth) { bc.updateAllDependencies(); } - ByteCodeClass.markDependencies(classes, nativeSources); + ByteCodeClass.markDependencies(classes, nativeTokens); List tmp = ByteCodeClass.clearUnmarked(classes); /*if(ByteCodeTranslator.verbose) { System.out.println("Classes removed from: " + classCount + " to " + classes.size()); @@ -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) {