2006-02-22 17:44:07 +03:00
|
|
|
/*
|
2009-06-02 11:38:21 +04:00
|
|
|
Copyright (C) 2002-2006, 2008, 2009 Jeroen Frijters
|
2006-02-22 17:44:07 +03:00
|
|
|
|
|
|
|
This software is provided 'as-is', without any express or implied
|
|
|
|
warranty. In no event will the authors be held liable for any damages
|
|
|
|
arising from the use of this software.
|
|
|
|
|
|
|
|
Permission is granted to anyone to use this software for any purpose,
|
|
|
|
including commercial applications, and to alter it and redistribute it
|
|
|
|
freely, subject to the following restrictions:
|
|
|
|
|
|
|
|
1. The origin of this software must not be misrepresented; you must not
|
|
|
|
claim that you wrote the original software. If you use this software
|
|
|
|
in a product, an acknowledgment in the product documentation would be
|
|
|
|
appreciated but is not required.
|
|
|
|
2. Altered source versions must be plainly marked as such, and must not be
|
|
|
|
misrepresented as being the original software.
|
|
|
|
3. This notice may not be removed or altered from any source distribution.
|
|
|
|
|
|
|
|
Jeroen Frijters
|
|
|
|
jeroen@frijters.net
|
|
|
|
|
|
|
|
*/
|
|
|
|
#if !COMPACT_FRAMEWORK
|
|
|
|
using System;
|
2008-03-04 10:25:36 +03:00
|
|
|
using System.Collections.Generic;
|
2006-02-22 17:44:07 +03:00
|
|
|
using System.Diagnostics;
|
|
|
|
using System.Reflection;
|
2008-11-14 11:42:07 +03:00
|
|
|
#if IKVM_REF_EMIT
|
|
|
|
using IKVM.Reflection.Emit;
|
|
|
|
#else
|
2006-02-22 17:44:07 +03:00
|
|
|
using System.Reflection.Emit;
|
2008-11-14 11:42:07 +03:00
|
|
|
#endif
|
2006-02-22 17:44:07 +03:00
|
|
|
|
|
|
|
namespace IKVM.Internal
|
|
|
|
{
|
2006-08-29 10:28:34 +04:00
|
|
|
[Flags]
|
|
|
|
enum CodeGenOptions
|
|
|
|
{
|
|
|
|
None = 0,
|
|
|
|
Debug = 1,
|
|
|
|
NoStackTraceInfo = 2,
|
|
|
|
StrictFinalFieldSemantics = 4,
|
|
|
|
NoJNI = 8,
|
2008-02-27 12:04:19 +03:00
|
|
|
RemoveAsserts = 16,
|
2006-08-29 10:28:34 +04:00
|
|
|
}
|
|
|
|
|
2006-09-12 13:57:36 +04:00
|
|
|
sealed class DynamicClassLoader : TypeWrapperFactory
|
2006-02-22 17:44:07 +03:00
|
|
|
{
|
2008-11-17 10:17:31 +03:00
|
|
|
// note that MangleNestedTypeName() assumes that there are less than 16 special characters
|
2006-07-27 15:57:33 +04:00
|
|
|
private static readonly char[] specialCharacters = { '\\', '+', ',', '[', ']', '*', '&', '\u0000' };
|
2006-07-24 12:21:11 +04:00
|
|
|
private static readonly string specialCharactersString = new String(specialCharacters);
|
2006-09-01 11:53:36 +04:00
|
|
|
#if !STATIC_COMPILER
|
2008-08-15 16:01:06 +04:00
|
|
|
private static List<AssemblyBuilder> saveDebugAssemblies;
|
2009-06-02 11:38:21 +04:00
|
|
|
private static List<DynamicClassLoader> saveClassLoaders;
|
2006-09-01 11:53:36 +04:00
|
|
|
#endif // !STATIC_COMPILER
|
2008-08-15 16:01:06 +04:00
|
|
|
private readonly Dictionary<string, TypeWrapper> dynamicTypes = new Dictionary<string, TypeWrapper>();
|
2006-09-01 11:53:36 +04:00
|
|
|
private ModuleBuilder moduleBuilder;
|
2007-09-12 10:47:48 +04:00
|
|
|
#if STATIC_COMPILER
|
2007-09-11 16:12:35 +04:00
|
|
|
private TypeBuilder proxyHelperContainer;
|
2008-08-15 16:01:06 +04:00
|
|
|
private List<TypeBuilder> proxyHelpers;
|
2007-09-12 10:47:48 +04:00
|
|
|
#endif // STATIC_COMPILER
|
2008-03-04 10:25:36 +03:00
|
|
|
private Dictionary<string, TypeBuilder> unloadables;
|
|
|
|
private TypeBuilder unloadableContainer;
|
2009-06-02 11:38:21 +04:00
|
|
|
#if !STATIC_COMPILER && !CLASSGC
|
|
|
|
private static DynamicClassLoader instance = new DynamicClassLoader(CreateModuleBuilder());
|
|
|
|
#endif
|
2006-02-22 17:44:07 +03:00
|
|
|
|
|
|
|
static DynamicClassLoader()
|
|
|
|
{
|
2006-09-01 11:53:36 +04:00
|
|
|
#if !STATIC_COMPILER
|
2009-06-02 11:38:21 +04:00
|
|
|
if(JVM.IsSaveDebugImage)
|
|
|
|
{
|
2009-07-13 12:00:18 +04:00
|
|
|
#if !CLASSGC
|
|
|
|
saveClassLoaders.Add(instance);
|
|
|
|
#endif
|
2009-06-02 11:38:21 +04:00
|
|
|
}
|
2006-02-22 17:44:07 +03:00
|
|
|
// TODO AppDomain.TypeResolve requires ControlAppDomain permission, but if we don't have that,
|
|
|
|
// we should handle that by disabling dynamic class loading
|
|
|
|
AppDomain.CurrentDomain.TypeResolve += new ResolveEventHandler(OnTypeResolve);
|
2006-09-01 11:53:36 +04:00
|
|
|
#endif // !STATIC_COMPILER
|
|
|
|
}
|
|
|
|
|
2006-09-12 13:57:36 +04:00
|
|
|
internal DynamicClassLoader(ModuleBuilder moduleBuilder)
|
2006-09-01 11:53:36 +04:00
|
|
|
{
|
|
|
|
this.moduleBuilder = moduleBuilder;
|
2006-07-27 15:57:33 +04:00
|
|
|
|
|
|
|
// Ref.Emit doesn't like the "<Module>" name for types
|
|
|
|
// (since it already defines a pseudo-type named <Module> for global methods and fields)
|
|
|
|
dynamicTypes.Add("<Module>", null);
|
2006-02-22 17:44:07 +03:00
|
|
|
}
|
|
|
|
|
2006-09-01 11:53:36 +04:00
|
|
|
#if !STATIC_COMPILER
|
2006-02-22 17:44:07 +03:00
|
|
|
private static Assembly OnTypeResolve(object sender, ResolveEventArgs args)
|
|
|
|
{
|
2008-08-15 16:01:06 +04:00
|
|
|
TypeWrapper type;
|
2009-06-02 11:38:21 +04:00
|
|
|
#if CLASSGC
|
|
|
|
DynamicClassLoader instance;
|
|
|
|
ClassLoaderWrapper loader = ClassLoaderWrapper.GetClassLoaderForDynamicJavaAssembly(args.RequestingAssembly);
|
|
|
|
if(loader == null)
|
2008-08-15 16:01:06 +04:00
|
|
|
{
|
2009-06-02 11:38:21 +04:00
|
|
|
return null;
|
2008-08-15 16:01:06 +04:00
|
|
|
}
|
2009-06-02 11:38:21 +04:00
|
|
|
instance = (DynamicClassLoader)loader.GetTypeWrapperFactory();
|
|
|
|
#endif
|
|
|
|
instance.dynamicTypes.TryGetValue(args.Name, out type);
|
2006-02-22 17:44:07 +03:00
|
|
|
if(type == null)
|
|
|
|
{
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
try
|
|
|
|
{
|
|
|
|
type.Finish();
|
|
|
|
}
|
|
|
|
catch(RetargetableJavaException x)
|
|
|
|
{
|
|
|
|
throw x.ToJava();
|
|
|
|
}
|
|
|
|
// NOTE We used to remove the type from the hashtable here, but that creates a race condition if
|
|
|
|
// another thread also fires the OnTypeResolve event while we're baking the type.
|
|
|
|
// I really would like to remove the type from the hashtable, but at the moment I don't see
|
|
|
|
// any way of doing that that wouldn't cause this race condition.
|
2006-05-05 15:21:15 +04:00
|
|
|
// UPDATE since we now also use the dynamicTypes hashtable to keep track of type names that
|
|
|
|
// have been used already, we cannot remove the keys.
|
2006-02-22 17:44:07 +03:00
|
|
|
return type.TypeAsTBD.Assembly;
|
|
|
|
}
|
2006-09-01 11:53:36 +04:00
|
|
|
#endif // !STATIC_COMPILER
|
2006-02-22 17:44:07 +03:00
|
|
|
|
2006-08-12 11:43:34 +04:00
|
|
|
internal static string EscapeName(string name)
|
2006-02-22 17:44:07 +03:00
|
|
|
{
|
2006-08-12 11:43:34 +04:00
|
|
|
// TODO the escaping of special characters is not required on .NET 2.0
|
|
|
|
// (but it doesn't really hurt that much either, the only overhead is the
|
|
|
|
// extra InnerClassAttribute to record the real name of the class)
|
|
|
|
// Note that even though .NET 2.0 automatically escapes the special characters,
|
|
|
|
// the name that gets passed in ResolveEventArgs.Name of the TypeResolve event
|
|
|
|
// contains the unescaped type name.
|
|
|
|
if(name.IndexOfAny(specialCharacters) >= 0)
|
2006-02-22 17:44:07 +03:00
|
|
|
{
|
2006-08-12 11:43:34 +04:00
|
|
|
System.Text.StringBuilder sb = new System.Text.StringBuilder();
|
|
|
|
foreach(char c in name)
|
2006-07-24 12:21:11 +04:00
|
|
|
{
|
2006-08-12 11:43:34 +04:00
|
|
|
if(specialCharactersString.IndexOf(c) >= 0)
|
2006-07-24 12:21:11 +04:00
|
|
|
{
|
2006-08-12 11:43:34 +04:00
|
|
|
if(c == 0)
|
2006-07-24 12:21:11 +04:00
|
|
|
{
|
2006-08-12 11:43:34 +04:00
|
|
|
// we can't escape the NUL character, so we replace it with a space.
|
|
|
|
sb.Append(' ');
|
|
|
|
continue;
|
2006-07-24 12:21:11 +04:00
|
|
|
}
|
2006-08-12 11:43:34 +04:00
|
|
|
sb.Append('\\');
|
2006-07-24 12:21:11 +04:00
|
|
|
}
|
2006-08-12 11:43:34 +04:00
|
|
|
sb.Append(c);
|
2006-07-24 12:21:11 +04:00
|
|
|
}
|
2006-08-12 11:43:34 +04:00
|
|
|
name = sb.ToString();
|
|
|
|
}
|
|
|
|
return name;
|
|
|
|
}
|
|
|
|
|
2007-06-12 13:45:30 +04:00
|
|
|
internal override bool ReserveName(string name)
|
|
|
|
{
|
2008-08-15 16:01:06 +04:00
|
|
|
lock(dynamicTypes)
|
2007-06-12 13:45:30 +04:00
|
|
|
{
|
|
|
|
if(dynamicTypes.ContainsKey(name))
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
dynamicTypes.Add(name, null);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-09-01 11:53:36 +04:00
|
|
|
private string AllocMangledName(string mangledTypeName)
|
2006-08-12 11:43:34 +04:00
|
|
|
{
|
2008-08-15 16:01:06 +04:00
|
|
|
lock(dynamicTypes)
|
2006-08-12 11:43:34 +04:00
|
|
|
{
|
|
|
|
mangledTypeName = EscapeName(mangledTypeName);
|
2006-07-26 11:57:18 +04:00
|
|
|
// FXBUG the CLR (both 1.1 and 2.0) doesn't like type names that end with a single period,
|
|
|
|
// it loses the trailing period in the name that gets passed in the TypeResolve event.
|
2006-07-06 17:53:51 +04:00
|
|
|
if(dynamicTypes.ContainsKey(mangledTypeName) || mangledTypeName.EndsWith("."))
|
2006-07-04 14:13:32 +04:00
|
|
|
{
|
2006-07-06 17:53:51 +04:00
|
|
|
#if STATIC_COMPILER
|
|
|
|
Tracer.Warning(Tracer.Compiler, "Class name clash: {0}", mangledTypeName);
|
2006-07-04 14:13:32 +04:00
|
|
|
#endif
|
2006-07-26 11:57:18 +04:00
|
|
|
// Java class names cannot contain slashes (since they are converted into periods),
|
|
|
|
// so we take advantage of that fact to create a unique name.
|
2006-09-01 11:53:36 +04:00
|
|
|
string baseName = mangledTypeName;
|
|
|
|
int instanceId = 0;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
mangledTypeName = baseName + "/" + (++instanceId);
|
|
|
|
} while(dynamicTypes.ContainsKey(mangledTypeName));
|
2006-07-04 14:13:32 +04:00
|
|
|
}
|
2006-07-06 17:53:51 +04:00
|
|
|
dynamicTypes.Add(mangledTypeName, null);
|
2006-02-22 17:44:07 +03:00
|
|
|
}
|
2006-07-26 18:16:52 +04:00
|
|
|
return mangledTypeName;
|
|
|
|
}
|
|
|
|
|
2008-08-15 16:01:06 +04:00
|
|
|
internal sealed override TypeWrapper DefineClassImpl(Dictionary<string, TypeWrapper> types, ClassFile f, ClassLoaderWrapper classLoader, object protectionDomain)
|
2006-07-26 18:16:52 +04:00
|
|
|
{
|
2006-09-12 13:57:36 +04:00
|
|
|
DynamicTypeWrapper type;
|
|
|
|
#if STATIC_COMPILER
|
|
|
|
type = new AotTypeWrapper(f, (CompilerClassLoader)classLoader);
|
|
|
|
#else
|
|
|
|
type = new DynamicTypeWrapper(f, classLoader);
|
|
|
|
#endif
|
2006-07-26 18:16:52 +04:00
|
|
|
// this step can throw a retargettable exception, if the class is incorrect
|
|
|
|
bool hasclinit;
|
|
|
|
type.CreateStep1(out hasclinit);
|
|
|
|
// now we can allocate the mangledTypeName, because the next step cannot fail
|
|
|
|
string mangledTypeName = AllocMangledName(f.Name);
|
2006-07-06 17:53:51 +04:00
|
|
|
// This step actually creates the TypeBuilder. It is not allowed to throw any exceptions,
|
|
|
|
// if an exception does occur, it is due to a programming error in the IKVM or CLR runtime
|
|
|
|
// and will cause a CriticalFailure and exit the process.
|
|
|
|
type.CreateStep2NoFail(hasclinit, mangledTypeName);
|
2008-08-15 16:01:06 +04:00
|
|
|
lock(types)
|
2006-02-22 17:44:07 +03:00
|
|
|
{
|
2006-07-06 17:53:51 +04:00
|
|
|
// in very extreme conditions another thread may have beaten us to it
|
|
|
|
// and loaded (not defined) a class with the same name, in that case
|
|
|
|
// we'll leak the the Reflection.Emit defined type. Also see the comment
|
|
|
|
// in ClassLoaderWrapper.RegisterInitiatingLoader().
|
2008-08-15 16:01:06 +04:00
|
|
|
TypeWrapper race;
|
|
|
|
types.TryGetValue(f.Name, out race);
|
2006-07-06 17:53:51 +04:00
|
|
|
if(race == null)
|
2006-02-22 17:44:07 +03:00
|
|
|
{
|
2008-08-15 16:01:06 +04:00
|
|
|
lock(dynamicTypes)
|
|
|
|
{
|
|
|
|
Debug.Assert(dynamicTypes.ContainsKey(mangledTypeName) && dynamicTypes[mangledTypeName] == null);
|
|
|
|
dynamicTypes[mangledTypeName] = type;
|
|
|
|
}
|
2006-07-06 17:53:51 +04:00
|
|
|
types[f.Name] = type;
|
2008-08-06 16:22:06 +04:00
|
|
|
#if !STATIC_COMPILER && !FIRST_PASS
|
2009-07-14 10:27:41 +04:00
|
|
|
java.lang.Class clazz = new java.lang.Class(null);
|
2009-03-02 09:30:13 +03:00
|
|
|
#if __MonoCS__
|
2008-05-20 11:36:50 +04:00
|
|
|
TypeWrapper.SetTypeWrapperHack(ref clazz.typeWrapper, type);
|
2009-03-02 09:30:13 +03:00
|
|
|
#else
|
|
|
|
clazz.typeWrapper = type;
|
|
|
|
#endif
|
2007-12-19 14:28:09 +03:00
|
|
|
clazz.pd = (java.security.ProtectionDomain)protectionDomain;
|
|
|
|
type.SetClassObject(clazz);
|
2006-04-10 13:09:09 +04:00
|
|
|
#endif
|
2006-02-22 17:44:07 +03:00
|
|
|
}
|
2006-07-06 17:53:51 +04:00
|
|
|
else
|
2006-02-22 17:44:07 +03:00
|
|
|
{
|
2006-07-06 17:53:51 +04:00
|
|
|
throw new LinkageError("duplicate class definition: " + f.Name);
|
2006-02-22 17:44:07 +03:00
|
|
|
}
|
|
|
|
}
|
2006-07-06 17:53:51 +04:00
|
|
|
return type;
|
2006-02-22 17:44:07 +03:00
|
|
|
}
|
|
|
|
|
2007-09-11 16:12:35 +04:00
|
|
|
#if STATIC_COMPILER
|
|
|
|
internal void DefineProxyHelper(Type type)
|
|
|
|
{
|
|
|
|
if(proxyHelperContainer == null)
|
|
|
|
{
|
|
|
|
proxyHelperContainer = moduleBuilder.DefineType("__<Proxy>", TypeAttributes.Public | TypeAttributes.Interface | TypeAttributes.Abstract);
|
|
|
|
AttributeHelper.HideFromJava(proxyHelperContainer);
|
|
|
|
AttributeHelper.SetEditorBrowsableNever(proxyHelperContainer);
|
2008-08-15 16:01:06 +04:00
|
|
|
proxyHelpers = new List<TypeBuilder>();
|
2007-09-11 16:12:35 +04:00
|
|
|
}
|
2008-03-04 10:25:36 +03:00
|
|
|
proxyHelpers.Add(proxyHelperContainer.DefineNestedType(MangleNestedTypeName(type.FullName), TypeAttributes.NestedPublic | TypeAttributes.Interface | TypeAttributes.Abstract, null, new Type[] { type }));
|
2007-09-11 16:12:35 +04:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
internal static string GetProxyHelperName(Type type)
|
|
|
|
{
|
2008-03-04 10:25:36 +03:00
|
|
|
return "__<Proxy>+" + MangleNestedTypeName(type.FullName);
|
|
|
|
}
|
|
|
|
|
|
|
|
private static string MangleNestedTypeName(string name)
|
|
|
|
{
|
|
|
|
System.Text.StringBuilder sb = new System.Text.StringBuilder();
|
|
|
|
foreach (char c in name)
|
2007-09-11 16:12:35 +04:00
|
|
|
{
|
|
|
|
int index = specialCharactersString.IndexOf(c);
|
|
|
|
if(c == '.')
|
|
|
|
{
|
2008-11-17 10:17:31 +03:00
|
|
|
sb.Append("_");
|
|
|
|
}
|
|
|
|
else if(c == '_')
|
|
|
|
{
|
|
|
|
sb.Append("^-");
|
2007-09-11 16:12:35 +04:00
|
|
|
}
|
|
|
|
else if(index == -1)
|
|
|
|
{
|
|
|
|
sb.Append(c);
|
2008-11-17 10:17:31 +03:00
|
|
|
if(c == '^')
|
2007-09-11 16:12:35 +04:00
|
|
|
{
|
|
|
|
sb.Append(c);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2008-11-17 10:17:31 +03:00
|
|
|
sb.Append('^').AppendFormat("{0:X1}", index);
|
2007-09-11 16:12:35 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return sb.ToString();
|
|
|
|
}
|
|
|
|
|
2008-03-04 10:25:36 +03:00
|
|
|
internal override Type DefineUnloadable(string name)
|
|
|
|
{
|
|
|
|
lock(this)
|
|
|
|
{
|
|
|
|
if(unloadables == null)
|
|
|
|
{
|
|
|
|
unloadables = new Dictionary<string, TypeBuilder>();
|
|
|
|
}
|
|
|
|
TypeBuilder type;
|
|
|
|
if(unloadables.TryGetValue(name, out type))
|
|
|
|
{
|
|
|
|
return type;
|
|
|
|
}
|
|
|
|
if(unloadableContainer == null)
|
|
|
|
{
|
|
|
|
unloadableContainer = moduleBuilder.DefineType("__<Unloadable>", TypeAttributes.Interface | TypeAttributes.Abstract);
|
|
|
|
AttributeHelper.HideFromJava(unloadableContainer);
|
|
|
|
}
|
|
|
|
type = unloadableContainer.DefineNestedType(MangleNestedTypeName(name), TypeAttributes.NestedPrivate | TypeAttributes.Interface | TypeAttributes.Abstract);
|
|
|
|
unloadables.Add(name, type);
|
|
|
|
return type;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-09-01 11:53:36 +04:00
|
|
|
internal void FinishAll()
|
2006-02-22 17:44:07 +03:00
|
|
|
{
|
2008-08-15 16:01:06 +04:00
|
|
|
Dictionary<TypeWrapper, TypeWrapper> done = new Dictionary<TypeWrapper, TypeWrapper>();
|
2006-05-05 15:21:15 +04:00
|
|
|
bool more = true;
|
|
|
|
while(more)
|
2006-02-22 17:44:07 +03:00
|
|
|
{
|
2006-05-05 15:21:15 +04:00
|
|
|
more = false;
|
2008-08-15 16:01:06 +04:00
|
|
|
List<TypeWrapper> l = new List<TypeWrapper>(dynamicTypes.Values);
|
2006-02-22 17:44:07 +03:00
|
|
|
foreach(TypeWrapper tw in l)
|
|
|
|
{
|
2006-07-26 18:16:52 +04:00
|
|
|
if(tw != null && !done.ContainsKey(tw))
|
2006-05-05 15:21:15 +04:00
|
|
|
{
|
|
|
|
more = true;
|
|
|
|
done.Add(tw, tw);
|
|
|
|
Tracer.Info(Tracer.Runtime, "Finishing {0}", tw.TypeAsTBD.FullName);
|
|
|
|
tw.Finish();
|
|
|
|
}
|
2006-02-22 17:44:07 +03:00
|
|
|
}
|
|
|
|
}
|
2008-03-04 10:25:36 +03:00
|
|
|
if(unloadableContainer != null)
|
|
|
|
{
|
|
|
|
unloadableContainer.CreateType();
|
|
|
|
foreach(TypeBuilder tb in unloadables.Values)
|
|
|
|
{
|
|
|
|
tb.CreateType();
|
|
|
|
}
|
|
|
|
}
|
2007-09-12 10:47:48 +04:00
|
|
|
#if STATIC_COMPILER
|
2007-09-11 16:12:35 +04:00
|
|
|
if(proxyHelperContainer != null)
|
|
|
|
{
|
|
|
|
proxyHelperContainer.CreateType();
|
|
|
|
foreach(TypeBuilder tb in proxyHelpers)
|
|
|
|
{
|
|
|
|
tb.CreateType();
|
|
|
|
}
|
|
|
|
}
|
2007-09-12 10:47:48 +04:00
|
|
|
#endif // STATIC_COMPILER
|
2006-02-22 17:44:07 +03:00
|
|
|
}
|
|
|
|
|
2006-04-10 13:09:09 +04:00
|
|
|
#if !STATIC_COMPILER
|
2009-05-26 14:17:57 +04:00
|
|
|
internal static void SaveDebugImages()
|
2006-02-22 17:44:07 +03:00
|
|
|
{
|
2006-09-01 11:53:36 +04:00
|
|
|
JVM.FinishingForDebugSave = true;
|
2009-06-02 11:38:21 +04:00
|
|
|
if (saveClassLoaders != null)
|
|
|
|
{
|
|
|
|
foreach (DynamicClassLoader instance in saveClassLoaders)
|
|
|
|
{
|
|
|
|
instance.FinishAll();
|
|
|
|
AssemblyBuilder ab = (AssemblyBuilder)instance.ModuleBuilder.Assembly;
|
|
|
|
ab.Save(ab.GetName().Name + ".dll");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (saveDebugAssemblies != null)
|
2006-02-22 17:44:07 +03:00
|
|
|
{
|
2009-06-02 11:38:21 +04:00
|
|
|
foreach (AssemblyBuilder ab in saveDebugAssemblies)
|
2006-02-22 17:44:07 +03:00
|
|
|
{
|
|
|
|
ab.Save(ab.GetName().Name + ".dll");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal static void RegisterForSaveDebug(AssemblyBuilder ab)
|
|
|
|
{
|
|
|
|
if(saveDebugAssemblies == null)
|
|
|
|
{
|
2008-08-15 16:01:06 +04:00
|
|
|
saveDebugAssemblies = new List<AssemblyBuilder>();
|
2006-02-22 17:44:07 +03:00
|
|
|
}
|
|
|
|
saveDebugAssemblies.Add(ab);
|
|
|
|
}
|
2006-09-01 11:53:36 +04:00
|
|
|
#endif
|
2006-02-22 17:44:07 +03:00
|
|
|
|
2006-09-01 11:53:36 +04:00
|
|
|
internal sealed override ModuleBuilder ModuleBuilder
|
2006-02-22 17:44:07 +03:00
|
|
|
{
|
|
|
|
get
|
|
|
|
{
|
2006-09-01 11:53:36 +04:00
|
|
|
return moduleBuilder;
|
2006-02-22 17:44:07 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-05-26 14:17:57 +04:00
|
|
|
internal static DynamicClassLoader Get(ClassLoaderWrapper loader)
|
|
|
|
{
|
|
|
|
#if STATIC_COMPILER
|
2009-06-02 11:38:21 +04:00
|
|
|
DynamicClassLoader instance = new DynamicClassLoader(((CompilerClassLoader)loader).CreateModuleBuilder());
|
|
|
|
#elif CLASSGC
|
|
|
|
DynamicClassLoader instance = new DynamicClassLoader(CreateModuleBuilder());
|
|
|
|
if(saveClassLoaders != null)
|
|
|
|
{
|
|
|
|
saveClassLoaders.Add(instance);
|
|
|
|
}
|
2009-05-26 14:17:57 +04:00
|
|
|
#endif
|
2009-06-02 11:38:21 +04:00
|
|
|
return instance;
|
2009-05-26 14:17:57 +04:00
|
|
|
}
|
|
|
|
|
2006-09-01 11:53:36 +04:00
|
|
|
#if !STATIC_COMPILER
|
|
|
|
private static ModuleBuilder CreateModuleBuilder()
|
2006-02-22 17:44:07 +03:00
|
|
|
{
|
|
|
|
AssemblyName name = new AssemblyName();
|
2009-07-13 12:00:18 +04:00
|
|
|
if(JVM.IsSaveDebugImage)
|
2006-02-22 17:44:07 +03:00
|
|
|
{
|
2009-07-13 12:00:18 +04:00
|
|
|
if(saveClassLoaders == null)
|
|
|
|
{
|
|
|
|
System.Threading.Interlocked.CompareExchange(ref saveClassLoaders, new List<DynamicClassLoader>(), null);
|
|
|
|
}
|
2009-06-02 11:38:21 +04:00
|
|
|
// we ignore the race condition (we could end up with multiple assemblies with the same name),
|
|
|
|
// because it is pretty harmless (you'll miss one of the ikvmdump-xx.dll files)
|
|
|
|
name.Name = "ikvmdump-" + saveClassLoaders.Count;
|
2006-02-22 17:44:07 +03:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2006-09-01 11:53:36 +04:00
|
|
|
name.Name = "ikvm_dynamic_assembly__" + (uint)Environment.TickCount;
|
2006-02-22 17:44:07 +03:00
|
|
|
}
|
|
|
|
DateTime now = DateTime.Now;
|
|
|
|
name.Version = new Version(now.Year, (now.Month * 100) + now.Day, (now.Hour * 100) + now.Minute, (now.Second * 1000) + now.Millisecond);
|
2009-05-24 10:54:24 +04:00
|
|
|
List<CustomAttributeBuilder> attribs = new List<CustomAttributeBuilder>();
|
|
|
|
if(Environment.Version.Major == 4 && Environment.Version.Minor == 0 && Environment.Version.Build == 20506)
|
|
|
|
{
|
|
|
|
// FXBUG workaround for MethodImpl bug in .NET 4.0 beta 1
|
|
|
|
attribs.Add(
|
|
|
|
new CustomAttributeBuilder(
|
|
|
|
Type.GetType("System.Security.SecurityRulesAttribute").GetConstructor(new Type[] { Type.GetType("System.Security.SecurityRuleSet") }),
|
|
|
|
new object[] { Type.GetType("System.Security.SecurityRuleSet").GetField("Level1").GetValue(null) }));
|
|
|
|
}
|
2009-06-02 11:38:21 +04:00
|
|
|
AssemblyBuilderAccess access;
|
|
|
|
if(JVM.IsSaveDebugImage)
|
|
|
|
{
|
|
|
|
access = AssemblyBuilderAccess.RunAndSave;
|
|
|
|
}
|
|
|
|
#if CLASSGC
|
|
|
|
else if(JVM.classUnloading)
|
|
|
|
{
|
|
|
|
access = AssemblyBuilderAccess.RunAndCollect;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
else
|
|
|
|
{
|
|
|
|
access = AssemblyBuilderAccess.Run;
|
|
|
|
}
|
2009-05-26 09:00:38 +04:00
|
|
|
AssemblyBuilder assemblyBuilder =
|
|
|
|
#if NET_4_0
|
2009-06-02 11:38:21 +04:00
|
|
|
AppDomain.CurrentDomain.DefineDynamicAssembly(name, access, null, true, attribs);
|
2009-05-26 09:00:38 +04:00
|
|
|
#else
|
2009-06-02 11:38:21 +04:00
|
|
|
AppDomain.CurrentDomain.DefineDynamicAssembly(name, access, null, null, null, null, null, true, attribs);
|
2009-05-26 09:00:38 +04:00
|
|
|
#endif
|
2009-06-18 10:14:55 +04:00
|
|
|
AttributeHelper.SetRuntimeCompatibilityAttribute(assemblyBuilder);
|
2009-07-27 12:06:41 +04:00
|
|
|
bool debug = JVM.EmitSymbols;
|
2006-09-01 11:53:36 +04:00
|
|
|
CustomAttributeBuilder debugAttr = new CustomAttributeBuilder(typeof(DebuggableAttribute).GetConstructor(new Type[] { typeof(bool), typeof(bool) }), new object[] { true, debug });
|
2006-02-22 17:44:07 +03:00
|
|
|
assemblyBuilder.SetCustomAttribute(debugAttr);
|
2009-05-29 11:47:20 +04:00
|
|
|
ModuleBuilder moduleBuilder = JVM.IsSaveDebugImage ? assemblyBuilder.DefineDynamicModule(name.Name, name.Name + ".dll", debug) : assemblyBuilder.DefineDynamicModule(name.Name, debug);
|
|
|
|
moduleBuilder.SetCustomAttribute(new CustomAttributeBuilder(typeof(IKVM.Attributes.JavaModuleAttribute).GetConstructor(Type.EmptyTypes), new object[0]));
|
|
|
|
return moduleBuilder;
|
2006-02-22 17:44:07 +03:00
|
|
|
}
|
2006-09-01 11:53:36 +04:00
|
|
|
#endif // !STATIC_COMPILER
|
2006-02-22 17:44:07 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif //COMPACT_FRAMEWORK
|