public MethodBody GetMethodBody(MethodDefinition targetMethod, XMethodDefinition sourceMethod) { var javaType = (XBuilder.JavaTypeDefinition)sourceMethod.DeclaringType; var className = javaType.ClassFile.ClassName; var source = javaType.ClassFile.Loader.TryGetClassSource(className); if (source == null) { return(null); } DexLookup dex = GetOrCreateDex(source, waitForResult: true); var methodDef = dex.GetMethod(targetMethod.Owner.Fullname, targetMethod.Name, targetMethod.Prototype.ToSignature()); return(methodDef == null ? null : methodDef.Body); }
public CacheEntry GetFromCacheImpl(MethodDefinition targetMethod, XMethodDefinition sourceMethod, AssemblyCompiler compiler, DexTargetPackage targetPackage) { if (_initialize == null) { return(null); } _initialize.Wait(); if (!IsEnabled) { return(null); } if (sourceMethod.ScopeId == null || sourceMethod.ScopeId == "(none)") { return(null); } if (IsUnderlyingCodeModified(sourceMethod)) { return(null); } Tuple <TypeEntry, MethodEntry> entry; string typeScopeId = sourceMethod.DeclaringType.ScopeId; string methodScopeId = sourceMethod.ScopeId; MethodDefinition cachedMethod; if (_methodsByScopeId.TryGetValue(Tuple.Create(typeScopeId, methodScopeId), out entry)) { cachedMethod = _dexLookup.GetMethod(entry.Item1.DexName, entry.Item2.DexName, entry.Item2.DexSignature); } else { // try directly in the dexlookup, for jar imports cachedMethod = _dexLookup.GetMethod(typeScopeId.Replace("/", "."), targetMethod.Name, targetMethod.Prototype.ToSignature()); } if (cachedMethod == null) { return(null); } if (cachedMethod.Body == null) { // I believe there is a bug in MethodExplicitInterfaceConverter generating // stubs for interfaces if they derive from an imported interface. // Bail out for now until this is fixed. DLog.Debug(DContext.CompilerCodeGenerator, "Compiler cache: no method body found on cached version of {0}, even though one was expected.", sourceMethod); return(null); } try { if (!Equals(cachedMethod.Prototype, targetMethod.Prototype)) { throw new Exception("internal error, got the wrong method."); } var body = DexMethodBodyCloner.Clone(targetMethod, cachedMethod); FixReferences(body, compiler, targetPackage); string className = entry != null ? entry.Item1.DexName : body.Owner.Owner.Fullname; var @class = _dexLookup.GetClass(className); return(new CacheEntry(body, entry != null ? entry.Item2 : null, entry != null ? _map.GetSourceCodePositions(entry.Item2) : null, @class.SourceFile)); } catch (CompilerCacheResolveException ex) { // This happens at the moment for methods using fields in the __generated class, // as well as for references to generated methods (mostly explicit interfac stubs) // during the IL conversion phase. // This also seems to happen for Framework-nested classes, maybe because these do // not get an entry in the map file. This should be fixed. // The number of these failures in my test is 890 out of ~12000. We gracefully // handle errors by re-compiling the method body. Debug.WriteLine(string.Format("Compiler cache: error while converting cached body: {0}: {1}. Not using cached body.", sourceMethod, ex.Message)); return(null); } catch (Exception ex) { DLog.Warning(DContext.CompilerCodeGenerator, "Compiler cache: exception while converting cached body: {0}: {1}. Not using cached body.", sourceMethod, ex.Message); Trace.WriteLine(string.Format("Compiler cache: error while converting cached body: {0}: {1}. Not using cached body.", sourceMethod, ex.Message)); return(null); } }