From 5ff74b58454d04a5f66bffb6977c951db84d24f2 Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Thu, 18 Dec 2025 19:45:29 +0200 Subject: [PATCH] Cache native source lookups for BytecodeTranslator --- .../tools/translator/BytecodeMethod.java | 56 ++++++++++++++++++- 1 file changed, 53 insertions(+), 3 deletions(-) diff --git a/vm/ByteCodeTranslator/src/com/codename1/tools/translator/BytecodeMethod.java b/vm/ByteCodeTranslator/src/com/codename1/tools/translator/BytecodeMethod.java index ff008acd94..1484cb7d4f 100644 --- a/vm/ByteCodeTranslator/src/com/codename1/tools/translator/BytecodeMethod.java +++ b/vm/ByteCodeTranslator/src/com/codename1/tools/translator/BytecodeMethod.java @@ -262,6 +262,29 @@ public String toString() { private Hashtable usedSigs; + + private static String[] nativeSourcesCache; + private static Map nativeClassUsageCache = new HashMap(); + private static Map nativeMethodUsageCache = new HashMap(); + + private static void resetNativeUsageCaches(String[] nativeSources) { + if (nativeSourcesCache != nativeSources) { + nativeSourcesCache = nativeSources; + nativeClassUsageCache = new HashMap(); + nativeMethodUsageCache = new HashMap(); + } + } + + private String functionPointer; + + private String getFunctionPointer() { + if (functionPointer == null) { + StringBuilder b = new StringBuilder(); + this.appendFunctionPointer(b); + functionPointer = b.toString(); + } + return functionPointer; + } // [ddyer 4/2017] avoid creating a lot of temporary objects. // more than 3x faster than the old way. @@ -307,6 +330,7 @@ public boolean isMethodUsed(BytecodeMethod bm0) { */ public boolean isMethodUsedByNative(String[] nativeSources, ByteCodeClass cls) { if (nativeSources == null) return false; + resetNativeUsageCaches(nativeSources); if (nativeSources == usedByNativeSources) { return usedByNative; } @@ -318,12 +342,32 @@ public boolean isMethodUsedByNative(String[] nativeSources, ByteCodeClass cls) { return false; } + String str = getFunctionPointer(); + Boolean cachedMethodUsage = nativeMethodUsageCache.get(str); + if (cachedMethodUsage != null) { + usedByNative = cachedMethodUsage.booleanValue(); + if (cls != null) { + if (cachedMethodUsage.booleanValue()) { + cls.setUsedByNative(true); + } else { + Boolean cachedClassUsage = nativeClassUsageCache.get(clsName); + if (cachedClassUsage != null && !cachedClassUsage.booleanValue()) { + cls.setUsedByNative(false); + } + } + } + return cachedMethodUsage.booleanValue(); + } + Boolean cachedClassUsage = nativeClassUsageCache.get(clsName); + if (cls != null && cachedClassUsage != null && !cachedClassUsage.booleanValue()) { + usedByNative = false; + cls.setUsedByNative(false); + nativeMethodUsageCache.put(str, Boolean.FALSE); + return false; + } // check native code - 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)) { @@ -334,10 +378,15 @@ public boolean isMethodUsedByNative(String[] nativeSources, ByteCodeClass cls) { usedByNative = true; if (cls != null) { cls.setUsedByNative(true); + nativeClassUsageCache.put(clsName, Boolean.TRUE); } + nativeMethodUsageCache.put(str, Boolean.TRUE); return true; } } + if (cls != null && cachedClassUsage == null) { + nativeClassUsageCache.put(clsName, Boolean.valueOf(foundClassName)); + } if (!foundClassName && cls != null) { // We didn't find the class at all. // Let's record that as it will save us time @@ -345,6 +394,7 @@ public boolean isMethodUsedByNative(String[] nativeSources, ByteCodeClass cls) { cls.setUsedByNative(false); } usedByNative = false; + nativeMethodUsageCache.put(str, Boolean.FALSE); return false; }