зеркало из https://github.com/mono/ikvm-fork.git
*** empty log message ***
This commit is contained in:
Родитель
5380a91247
Коммит
90982544bd
|
@ -2419,6 +2419,7 @@ sun/misc/Ref.java
|
|||
../../classpath/javax/swing/SizeRequirements.java
|
||||
../../classpath/javax/swing/SizeSequence.java
|
||||
../../classpath/javax/swing/SortingFocusTraversalPolicy.java
|
||||
../../classpath/javax/swing/SpinnerDateModel.java
|
||||
../../classpath/javax/swing/SpinnerListModel.java
|
||||
../../classpath/javax/swing/SpinnerModel.java
|
||||
../../classpath/javax/swing/SpinnerNumberModel.java
|
||||
|
@ -2734,7 +2735,7 @@ sun/misc/Ref.java
|
|||
../../classpath/gnu/xml/aelfred2/XmlReader.java
|
||||
../../classpath/gnu/xml/dom/Consumer.java
|
||||
../../classpath/gnu/xml/dom/DomAttr.java
|
||||
../../classpath/gnu/xml/dom/DomCDATA.java
|
||||
../../classpath/gnu/xml/dom/DomCDATASection.java
|
||||
../../classpath/gnu/xml/dom/DomCharacterData.java
|
||||
../../classpath/gnu/xml/dom/DomComment.java
|
||||
../../classpath/gnu/xml/dom/DomDoctype.java
|
||||
|
@ -2742,13 +2743,13 @@ sun/misc/Ref.java
|
|||
../../classpath/gnu/xml/dom/DomDocumentBuilder.java
|
||||
../../classpath/gnu/xml/dom/DomDocumentBuilderFactory.java
|
||||
../../classpath/gnu/xml/dom/DomDocumentConfiguration.java
|
||||
../../classpath/gnu/xml/dom/DomDocumentFragment.java
|
||||
../../classpath/gnu/xml/dom/DomDOMException.java
|
||||
../../classpath/gnu/xml/dom/DomElement.java
|
||||
../../classpath/gnu/xml/dom/DomEntity.java
|
||||
../../classpath/gnu/xml/dom/DomEntityReference.java
|
||||
../../classpath/gnu/xml/dom/DomEvent.java
|
||||
../../classpath/gnu/xml/dom/DomEx.java
|
||||
../../classpath/gnu/xml/dom/DomExtern.java
|
||||
../../classpath/gnu/xml/dom/DomFragment.java
|
||||
../../classpath/gnu/xml/dom/DomImpl.java
|
||||
../../classpath/gnu/xml/dom/DomIterator.java
|
||||
../../classpath/gnu/xml/dom/DomNamedNodeMap.java
|
||||
|
@ -2757,7 +2758,7 @@ sun/misc/Ref.java
|
|||
../../classpath/gnu/xml/dom/DomNotation.java
|
||||
../../classpath/gnu/xml/dom/DomNsNode.java
|
||||
../../classpath/gnu/xml/dom/DomNSResolverContext.java
|
||||
../../classpath/gnu/xml/dom/DomPI.java
|
||||
../../classpath/gnu/xml/dom/DomProcessingInstruction.java
|
||||
../../classpath/gnu/xml/dom/DomText.java
|
||||
../../classpath/gnu/xml/dom/DomXPathExpression.java
|
||||
../../classpath/gnu/xml/dom/DomXPathNSResolver.java
|
||||
|
@ -2767,7 +2768,7 @@ sun/misc/Ref.java
|
|||
../../classpath/gnu/xml/dom/ImplementationList.java
|
||||
../../classpath/gnu/xml/dom/ImplementationSource.java
|
||||
../../classpath/gnu/xml/dom/JAXPFactory.java
|
||||
../../classpath/gnu/xml/dom/ls/DomLSEx.java
|
||||
../../classpath/gnu/xml/dom/ls/DomLSException.java
|
||||
../../classpath/gnu/xml/dom/ls/DomLSInput.java
|
||||
../../classpath/gnu/xml/dom/ls/DomLSOutput.java
|
||||
../../classpath/gnu/xml/dom/ls/DomLSParser.java
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
</target>
|
||||
|
||||
<target name="IKVM.GNU.Classpath.dll" depends="classes">
|
||||
<exec program="${nant.project.basedir}/../bin/ikvmc.exe" useruntimeengine="true" commandline="-version:0.11.* ${signoption} -monoBugWorkaround -opt:fields -nojni -out:IKVM.GNU.Classpath.dll -remap:map.xml -exclude:exclude.lst -target:library -recurse:./*.class -recurse:${Classpath.dir}/*.class -recurse:${Classpath.dir}/resource/*.properties mscorlib.jar System.jar System.Xml.jar -resource:lib/security/classpath.security=classpath.security" />
|
||||
<exec program="${nant.project.basedir}/../bin/ikvmc.exe" useruntimeengine="true" commandline="-version:0.11.* ${signoption} -monoBugWorkaround -enabletls -opt:fields -nojni -out:IKVM.GNU.Classpath.dll -remap:map.xml -exclude:exclude.lst -target:library -recurse:./*.class -recurse:${Classpath.dir}/*.class -recurse:${Classpath.dir}/resource/*.properties mscorlib.jar System.jar System.Xml.jar -resource:lib/security/classpath.security=classpath.security" />
|
||||
<copy file="IKVM.GNU.Classpath.dll" tofile="../bin/IKVM.GNU.Classpath.dll.new" />
|
||||
<if propertytrue="nant.platform.win32">
|
||||
<call target="peverify-classpath"/>
|
||||
|
|
|
@ -174,37 +174,34 @@ final class VMClassLoader
|
|||
*/
|
||||
static Enumeration getResources(String name) throws IOException
|
||||
{
|
||||
synchronized(nestedGetResourcesHack)
|
||||
{
|
||||
if(cli.System.Threading.Thread.GetData(nestedGetResourcesHack) != null)
|
||||
if(__tls_nestedGetResourcesHack)
|
||||
{
|
||||
return gnu.java.util.EmptyEnumeration.getInstance();
|
||||
}
|
||||
__tls_nestedGetResourcesHack = true;
|
||||
try
|
||||
{
|
||||
Assembly[] assemblies = findResourceAssemblies(name);
|
||||
java.util.Vector v = new java.util.Vector();
|
||||
for(int i = 0; i < assemblies.length; i++)
|
||||
{
|
||||
return gnu.java.util.EmptyEnumeration.getInstance();
|
||||
v.addElement(new URL("ikvmres", assemblies[i].get_FullName(), -1, "/" + name));
|
||||
}
|
||||
cli.System.Threading.Thread.SetData(nestedGetResourcesHack, "");
|
||||
try
|
||||
Enumeration e = v.elements();
|
||||
ClassLoader bootstrap = getBootstrapClassLoader();
|
||||
if(bootstrap != null)
|
||||
{
|
||||
Assembly[] assemblies = findResourceAssemblies(name);
|
||||
java.util.Vector v = new java.util.Vector();
|
||||
for(int i = 0; i < assemblies.length; i++)
|
||||
{
|
||||
v.addElement(new URL("ikvmres", assemblies[i].get_FullName(), -1, "/" + name));
|
||||
}
|
||||
Enumeration e = v.elements();
|
||||
ClassLoader bootstrap = getBootstrapClassLoader();
|
||||
if(bootstrap != null)
|
||||
{
|
||||
e = new DoubleEnumeration(e, bootstrap.getResources(name));
|
||||
}
|
||||
return e;
|
||||
e = new DoubleEnumeration(e, bootstrap.getResources(name));
|
||||
}
|
||||
finally
|
||||
{
|
||||
cli.System.Threading.Thread.SetData(nestedGetResourcesHack, null);
|
||||
}
|
||||
}
|
||||
return e;
|
||||
}
|
||||
finally
|
||||
{
|
||||
__tls_nestedGetResourcesHack = false;
|
||||
}
|
||||
}
|
||||
|
||||
private static cli.System.LocalDataStoreSlot nestedGetResourcesHack = cli.System.Threading.Thread.AllocateDataSlot();
|
||||
private static boolean __tls_nestedGetResourcesHack;
|
||||
|
||||
/**
|
||||
* Helper to get a package from the bootstrap class loader. The default
|
||||
|
@ -252,15 +249,9 @@ final class VMClassLoader
|
|||
if(packages == null)
|
||||
{
|
||||
ClassLoader boot = getBootstrapClassLoader();
|
||||
if(boot != null)
|
||||
if(boot != null && __tls_nestedGetResourcesHack)
|
||||
{
|
||||
synchronized(nestedGetResourcesHack)
|
||||
{
|
||||
if(cli.System.Threading.Thread.GetData(nestedGetResourcesHack) != null)
|
||||
{
|
||||
return new Package[0];
|
||||
}
|
||||
}
|
||||
return new Package[0];
|
||||
}
|
||||
HashMap h = new HashMap();
|
||||
Assembly[] assemblies = AppDomain.get_CurrentDomain().GetAssemblies();
|
||||
|
@ -283,17 +274,14 @@ final class VMClassLoader
|
|||
if(boot != null)
|
||||
{
|
||||
Package[] pkgboot;
|
||||
synchronized(nestedGetResourcesHack)
|
||||
__tls_nestedGetResourcesHack = true;
|
||||
try
|
||||
{
|
||||
cli.System.Threading.Thread.SetData(nestedGetResourcesHack, "");
|
||||
try
|
||||
{
|
||||
pkgboot = boot.getPackages();
|
||||
}
|
||||
finally
|
||||
{
|
||||
cli.System.Threading.Thread.SetData(nestedGetResourcesHack, null);
|
||||
}
|
||||
pkgboot = boot.getPackages();
|
||||
}
|
||||
finally
|
||||
{
|
||||
__tls_nestedGetResourcesHack = false;
|
||||
}
|
||||
Collection c = h.values();
|
||||
packages = new Package[c.size() + pkgboot.length];
|
||||
|
|
|
@ -6,7 +6,8 @@ final class VMThread
|
|||
{
|
||||
private static final Object countLock = new Object();
|
||||
private static int nonDaemonCount;
|
||||
private static final cli.System.LocalDataStoreSlot localDataStoreSlot = cli.System.Threading.Thread.AllocateDataSlot();
|
||||
private static Thread __tls_javaThread;
|
||||
private static Object __tls_cleanup;
|
||||
private cli.System.WeakReference nativeThreadReference;
|
||||
|
||||
// Note: when this thread dies, this reference is *not* cleared
|
||||
|
@ -122,7 +123,8 @@ final class VMThread
|
|||
synchronized(vmthread)
|
||||
{
|
||||
vmthread.cleanup();
|
||||
cli.System.Threading.Thread.SetData(localDataStoreSlot, null);
|
||||
__tls_javaThread = null;
|
||||
__tls_cleanup = null;
|
||||
VMThread joinWaiter = vmthread.firstJoinWaiter;
|
||||
while(joinWaiter != null)
|
||||
{
|
||||
|
@ -163,8 +165,7 @@ final class VMThread
|
|||
|
||||
static void setThreadGroup(ThreadGroup group)
|
||||
{
|
||||
Thread javaThread = (Thread)cli.System.Threading.Thread.GetData(localDataStoreSlot);
|
||||
if(javaThread == null)
|
||||
if(__tls_javaThread == null)
|
||||
{
|
||||
newThread(group);
|
||||
}
|
||||
|
@ -283,7 +284,7 @@ final class VMThread
|
|||
{
|
||||
public void Invoke()
|
||||
{
|
||||
cli.System.Threading.Thread.SetData(localDataStoreSlot, thread);
|
||||
__tls_javaThread = thread;
|
||||
run();
|
||||
}
|
||||
});
|
||||
|
@ -508,8 +509,8 @@ final class VMThread
|
|||
}
|
||||
}
|
||||
vmThread.thread = javaThread;
|
||||
cli.System.Threading.Thread.SetData(localDataStoreSlot, javaThread);
|
||||
cli.System.Threading.Thread.SetData(cli.System.Threading.Thread.GetNamedDataSlot("ikvm-thread-hack"), new CleanupHack(javaThread));
|
||||
__tls_javaThread = javaThread;
|
||||
__tls_cleanup = new CleanupHack(javaThread);
|
||||
javaThread.group = group;
|
||||
javaThread.group.addThread(javaThread);
|
||||
InheritableThreadLocal.newChildThread(javaThread);
|
||||
|
@ -518,10 +519,10 @@ final class VMThread
|
|||
|
||||
static Thread currentThread()
|
||||
{
|
||||
Thread javaThread = (Thread)cli.System.Threading.Thread.GetData(localDataStoreSlot);
|
||||
Thread javaThread = __tls_javaThread;
|
||||
if(javaThread == null)
|
||||
{
|
||||
javaThread = newThread(ThreadGroup.root);
|
||||
__tls_javaThread = javaThread = newThread(ThreadGroup.root);
|
||||
}
|
||||
return javaThread;
|
||||
}
|
||||
|
|
|
@ -57,14 +57,14 @@ final class VMAccessController
|
|||
* call stack. We use this to remember which context object corresponds to
|
||||
* which call.
|
||||
*/
|
||||
private static final cli.System.LocalDataStoreSlot contexts = cli.System.Threading.Thread.AllocateDataSlot();
|
||||
private static LinkedList __tls_contexts;
|
||||
|
||||
/**
|
||||
* This is a Boolean that, if set, tells getContext that it has already
|
||||
* been called once, allowing us to handle recursive permission checks
|
||||
* caused by methods getContext calls.
|
||||
*/
|
||||
private static final cli.System.LocalDataStoreSlot inGetContext = cli.System.Threading.Thread.AllocateDataSlot();
|
||||
private static boolean __tls_inGetContext;
|
||||
|
||||
/**
|
||||
* And we return this all-permissive context to ensure that privileged
|
||||
|
@ -111,11 +111,11 @@ final class VMAccessController
|
|||
{
|
||||
if (DEBUG)
|
||||
debug("pushing " + acc);
|
||||
LinkedList stack = (LinkedList) cli.System.Threading.Thread.GetData(contexts);
|
||||
LinkedList stack = __tls_contexts;
|
||||
if (stack == null)
|
||||
{
|
||||
stack = new LinkedList();
|
||||
cli.System.Threading.Thread.SetData(contexts, stack);
|
||||
__tls_contexts = stack;
|
||||
}
|
||||
stack.addFirst(acc);
|
||||
}
|
||||
|
@ -133,12 +133,12 @@ final class VMAccessController
|
|||
|
||||
// Stack should never be null, nor should it be empty, if this method
|
||||
// and its counterpart has been called properly.
|
||||
LinkedList stack = (LinkedList) cli.System.Threading.Thread.GetData(contexts);
|
||||
LinkedList stack = __tls_contexts;
|
||||
if (stack != null)
|
||||
{
|
||||
stack.removeFirst();
|
||||
if (stack.isEmpty())
|
||||
cli.System.Threading.Thread.SetData(contexts, null);
|
||||
__tls_contexts = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -157,15 +157,14 @@ final class VMAccessController
|
|||
//
|
||||
// XXX is this necessary? We should verify if there are any calls in
|
||||
// the stack below this method that require permission checks.
|
||||
Boolean inCall = (Boolean) cli.System.Threading.Thread.GetData(inGetContext);
|
||||
if (inCall != null && inCall.booleanValue())
|
||||
if (__tls_inGetContext)
|
||||
{
|
||||
if (DEBUG)
|
||||
debug("already in getContext");
|
||||
return DEFAULT_CONTEXT;
|
||||
}
|
||||
|
||||
cli.System.Threading.Thread.SetData(inGetContext, Boolean.TRUE);
|
||||
__tls_inGetContext = true;
|
||||
|
||||
Object[][] stack = getStack();
|
||||
Class[] classes = (Class[]) stack[0];
|
||||
|
@ -210,7 +209,7 @@ final class VMAccessController
|
|||
{
|
||||
// If there was a call to doPrivileged with a supplied context,
|
||||
// return that context.
|
||||
LinkedList l = (LinkedList) cli.System.Threading.Thread.GetData(contexts);
|
||||
LinkedList l = __tls_contexts;
|
||||
if (l != null)
|
||||
context = (AccessControlContext) l.getFirst();
|
||||
privileged = 1;
|
||||
|
@ -245,7 +244,7 @@ final class VMAccessController
|
|||
else
|
||||
context = new AccessControlContext(result);
|
||||
|
||||
cli.System.Threading.Thread.SetData(inGetContext, Boolean.FALSE);
|
||||
__tls_inGetContext = false;
|
||||
return context;
|
||||
}
|
||||
|
||||
|
|
|
@ -120,6 +120,8 @@ class Compiler
|
|||
Console.Error.WriteLine(" -Xtrace:<string> Displays all tracepoints with the given name");
|
||||
Console.Error.WriteLine(" -Xmethodtrace:<string> Build tracing into the specified output methods");
|
||||
Console.Error.WriteLine(" -monoBugWorkaround Workaround metadata bug in Mono 1.0.5 and 1.1.3");
|
||||
Console.Error.WriteLine(" -enabletls Apply ThreadStaticAttribute to fields starting");
|
||||
Console.Error.WriteLine(" with __tls_");
|
||||
return 1;
|
||||
}
|
||||
foreach(string s in arglist)
|
||||
|
@ -359,6 +361,10 @@ class Compiler
|
|||
{
|
||||
options.monoBugWorkaround = true;
|
||||
}
|
||||
else if(s == "-enabletls")
|
||||
{
|
||||
options.enableTls = true;
|
||||
}
|
||||
else if(s == "-opt:fields")
|
||||
{
|
||||
options.removeUnusedFields = true;
|
||||
|
|
|
@ -370,16 +370,22 @@ namespace IKVM.Runtime
|
|||
|
||||
sealed class JniHelper
|
||||
{
|
||||
//[DllImport("ikvm-native", EntryPoint="_ikvm_LoadLibrary@4")]
|
||||
[DllImport("ikvm-native")]
|
||||
private static extern IntPtr ikvm_LoadLibrary(string filename);
|
||||
//[DllImport("ikvm-native", EntryPoint="_ikvm_FreeLibrary@4")]
|
||||
[DllImport("ikvm-native")]
|
||||
private static extern void ikvm_FreeLibrary(IntPtr handle);
|
||||
//[DllImport("ikvm-native", EntryPoint="_ikvm_GetProcAddress@12")]
|
||||
[DllImport("ikvm-native")]
|
||||
internal static extern IntPtr ikvm_GetProcAddress(IntPtr handle, string name, int argc);
|
||||
//[DllImport("ikvm-native", EntryPoint="_ikvm_CallOnLoad@12")]
|
||||
[DllImport("ikvm-native")]
|
||||
private unsafe static extern int ikvm_CallOnLoad(IntPtr method, void* jvm, void* reserved);
|
||||
//[DllImport("ikvm-native", EntryPoint="_ikvm_GetJNIEnvVTable@0")]
|
||||
[DllImport("ikvm-native")]
|
||||
internal unsafe static extern void** ikvm_GetJNIEnvVTable();
|
||||
//[DllImport("ikvm-native", EntryPoint="_ikvm_MarshalDelegate@4")]
|
||||
[DllImport("ikvm-native")]
|
||||
internal unsafe static extern void* ikvm_MarshalDelegate(Delegate d);
|
||||
|
||||
|
@ -1639,13 +1645,18 @@ namespace IKVM.Runtime
|
|||
{
|
||||
TypeWrapper wrapper = IKVM.NativeCode.java.lang.VMClass.getWrapperFromClass(pEnv->UnwrapRef(clazz));
|
||||
wrapper.Finish();
|
||||
MethodWrapper mw = wrapper.GetMethodWrapper(StringFromUTF8(name), StringFromUTF8(sig).Replace('/', '.'), true);
|
||||
if(mw != null)
|
||||
string methodsig = StringFromUTF8(sig);
|
||||
// don't allow dotted names!
|
||||
if(methodsig.IndexOf('.') < 0)
|
||||
{
|
||||
if(mw.IsStatic == isstatic)
|
||||
MethodWrapper mw = wrapper.GetMethodWrapper(StringFromUTF8(name), methodsig.Replace('/', '.'), true);
|
||||
if(mw != null)
|
||||
{
|
||||
mw.Link();
|
||||
return mw.Cookie;
|
||||
if(mw.IsStatic == isstatic)
|
||||
{
|
||||
mw.Link();
|
||||
return mw.Cookie;
|
||||
}
|
||||
}
|
||||
}
|
||||
SetPendingException(pEnv, JavaException.NoSuchMethodError("{0}{1}", StringFromUTF8(name), StringFromUTF8(sig).Replace('/', '.')));
|
||||
|
@ -1852,12 +1863,17 @@ namespace IKVM.Runtime
|
|||
{
|
||||
TypeWrapper wrapper = IKVM.NativeCode.java.lang.VMClass.getWrapperFromClass(pEnv->UnwrapRef(clazz));
|
||||
wrapper.Finish();
|
||||
FieldWrapper fw = wrapper.GetFieldWrapper(StringFromUTF8(name), StringFromUTF8(sig).Replace('/', '.'));
|
||||
if(fw != null)
|
||||
string fieldsig = StringFromUTF8(sig);
|
||||
// don't allow dotted names!
|
||||
if(fieldsig.IndexOf('.') < 0)
|
||||
{
|
||||
if(fw.IsStatic == isstatic)
|
||||
FieldWrapper fw = wrapper.GetFieldWrapper(StringFromUTF8(name), fieldsig.Replace('/', '.'));
|
||||
if(fw != null)
|
||||
{
|
||||
return fw.Cookie;
|
||||
if(fw.IsStatic == isstatic)
|
||||
{
|
||||
return fw.Cookie;
|
||||
}
|
||||
}
|
||||
}
|
||||
SetPendingException(pEnv, JavaException.NoSuchFieldError(StringFromUTF8(name)));
|
||||
|
@ -2872,8 +2888,14 @@ namespace IKVM.Runtime
|
|||
wrapper.Finish();
|
||||
for(int i = 0; i < nMethods; i++)
|
||||
{
|
||||
// TODO this won't work when we're putting the JNI methods in jniproxy.dll
|
||||
FieldInfo fi = wrapper.TypeAsTBD.GetField(JNI.METHOD_PTR_FIELD_PREFIX + StringFromUTF8(methods[i].name) + StringFromUTF8(methods[i].signature).Replace('/', '.') + ">", BindingFlags.Static | BindingFlags.NonPublic);
|
||||
string methodsig = StringFromUTF8(methods[i].signature);
|
||||
FieldInfo fi = null;
|
||||
// don't allow dotted names!
|
||||
if(methodsig.IndexOf('.') < 0)
|
||||
{
|
||||
// TODO this won't work when we're putting the JNI methods in jniproxy.dll
|
||||
fi = wrapper.TypeAsTBD.GetField(JNI.METHOD_PTR_FIELD_PREFIX + StringFromUTF8(methods[i].name) + methodsig.Replace('/', '.') + ">", BindingFlags.Static | BindingFlags.NonPublic);
|
||||
}
|
||||
if(fi == null)
|
||||
{
|
||||
SetPendingException(pEnv, JavaException.NoSuchMethodError(StringFromUTF8(methods[i].name)));
|
||||
|
@ -3139,7 +3161,8 @@ namespace IKVM.Runtime
|
|||
{
|
||||
for(int i = 0; i < GlobalRefs.weakRefs.Length; i++)
|
||||
{
|
||||
if(!GlobalRefs.weakRefs[i].IsAllocated)
|
||||
// MONOBUG GCHandle.IsAllocated is horribly broken, so we also check the value of the handle
|
||||
if(!GlobalRefs.weakRefs[i].IsAllocated || (IntPtr)GlobalRefs.weakRefs[i] == IntPtr.Zero)
|
||||
{
|
||||
GlobalRefs.weakRefs[i] = GCHandle.Alloc(o, GCHandleType.WeakTrackResurrection);
|
||||
return (IntPtr)(- (i | (1 << 30)));
|
||||
|
|
|
@ -74,7 +74,8 @@ class MemberWrapper
|
|||
{
|
||||
lock(this)
|
||||
{
|
||||
if(!handle.IsAllocated)
|
||||
// MONOBUG GCHandle.IsAllocated is horribly broken, so we also check the value of the handle
|
||||
if(!handle.IsAllocated || (IntPtr)handle == IntPtr.Zero)
|
||||
{
|
||||
handle = System.Runtime.InteropServices.GCHandle.Alloc(this, System.Runtime.InteropServices.GCHandleType.Weak);
|
||||
}
|
||||
|
|
|
@ -89,9 +89,9 @@ class EmitHelper
|
|||
ilgen.Emit(OpCodes.Isinst, type);
|
||||
ilgen.Emit(OpCodes.Dup);
|
||||
Label ok = ilgen.DefineLabel();
|
||||
ilgen.Emit(OpCodes.Brtrue, ok);
|
||||
ilgen.Emit(OpCodes.Brtrue_S, ok);
|
||||
ilgen.Emit(OpCodes.Ldloc, lb);
|
||||
ilgen.Emit(OpCodes.Brfalse, ok); // handle null
|
||||
ilgen.Emit(OpCodes.Brfalse_S, ok); // handle null
|
||||
ilgen.Emit(OpCodes.Ldtoken, type);
|
||||
ilgen.Emit(OpCodes.Ldloc, lb);
|
||||
ilgen.Emit(OpCodes.Call, verboseCastFailure);
|
||||
|
@ -102,6 +102,23 @@ class EmitHelper
|
|||
ilgen.Emit(OpCodes.Castclass, type);
|
||||
}
|
||||
}
|
||||
|
||||
// This is basically the same as Castclass, except that it
|
||||
// throws an IncompatibleClassChangeError on failure.
|
||||
internal static void EmitAssertType(ILGenerator ilgen, Type type)
|
||||
{
|
||||
LocalBuilder lb = ilgen.DeclareLocal(typeof(object));
|
||||
ilgen.Emit(OpCodes.Stloc, lb);
|
||||
ilgen.Emit(OpCodes.Ldloc, lb);
|
||||
ilgen.Emit(OpCodes.Isinst, type);
|
||||
ilgen.Emit(OpCodes.Dup);
|
||||
Label ok = ilgen.DefineLabel();
|
||||
ilgen.Emit(OpCodes.Brtrue_S, ok);
|
||||
ilgen.Emit(OpCodes.Ldloc, lb);
|
||||
ilgen.Emit(OpCodes.Brfalse_S, ok); // handle null
|
||||
EmitHelper.Throw(ilgen, "java.lang.IncompatibleClassChangeError");
|
||||
ilgen.MarkLabel(ok);
|
||||
}
|
||||
}
|
||||
|
||||
class AttributeHelper
|
||||
|
@ -1391,7 +1408,8 @@ abstract class TypeWrapper
|
|||
// for any interface reference
|
||||
else if(IsInterfaceOrInterfaceArray && (sourceType == null || sourceType.IsUnloadable || !sourceType.IsAssignableTo(this)))
|
||||
{
|
||||
ilgen.Emit(OpCodes.Castclass, TypeAsTBD);
|
||||
EmitHelper.EmitAssertType(ilgen, TypeAsTBD);
|
||||
Profiler.Count("InterfaceDownCast");
|
||||
}
|
||||
else if(IsNonPrimitiveValueType)
|
||||
{
|
||||
|
@ -2720,6 +2738,11 @@ sealed class DynamicTypeWrapper : TypeWrapper
|
|||
setModifiers = true;
|
||||
}
|
||||
field = typeBuilder.DefineField(fieldName, type, attribs);
|
||||
if(JVM.IsTlsEnabled && fieldName.StartsWith("__tls_"))
|
||||
{
|
||||
CustomAttributeBuilder threadStaticAttrib = new CustomAttributeBuilder(typeof(ThreadStaticAttribute).GetConstructor(Type.EmptyTypes), new object[0]);
|
||||
field.SetCustomAttribute(threadStaticAttrib);
|
||||
}
|
||||
if(fld.IsTransient)
|
||||
{
|
||||
CustomAttributeBuilder transientAttrib = new CustomAttributeBuilder(typeof(NonSerializedAttribute).GetConstructor(Type.EmptyTypes), new object[0]);
|
||||
|
|
|
@ -1987,6 +1987,9 @@ class Compiler
|
|||
}
|
||||
else
|
||||
{
|
||||
// NOTE for verifiability it is expressly *not* required that the
|
||||
// value matches the array type, so we don't need to handle interface
|
||||
// references here.
|
||||
ilGenerator.Emit(OpCodes.Stelem_Ref);
|
||||
}
|
||||
}
|
||||
|
@ -2789,8 +2792,7 @@ class Compiler
|
|||
TypeWrapper tw = ma.GetRawStackTypeWrapper(instructionIndex, args.Length - 1 - i);
|
||||
if(tw.IsUnloadable || (args[i].IsInterfaceOrInterfaceArray && !tw.IsAssignableTo(args[i])))
|
||||
{
|
||||
// TODO ideally, instead of an InvalidCastException, the castclass should throw a IncompatibleClassChangeError
|
||||
ilGenerator.Emit(OpCodes.Castclass, args[i].TypeAsTBD);
|
||||
EmitHelper.EmitAssertType(ilGenerator, args[i].TypeAsTBD);
|
||||
Profiler.Count("InterfaceDownCast");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -145,7 +145,7 @@ namespace IKVM.Internal.MapXml
|
|||
}
|
||||
if(tw.IsGhost)
|
||||
{
|
||||
tw.EmitConvStackTypeToSignatureType(ilgen, tw);
|
||||
tw.EmitConvStackTypeToSignatureType(ilgen, null);
|
||||
}
|
||||
temps[j] = ilgen.DeclareLocal(tw.TypeAsSignatureType);
|
||||
ilgen.Emit(OpCodes.Stloc, temps[j]);
|
||||
|
|
|
@ -45,12 +45,8 @@ namespace IKVM.Runtime
|
|||
{
|
||||
}
|
||||
|
||||
public static string[] Glob(string arg)
|
||||
private static string[] Glob(string arg)
|
||||
{
|
||||
if(IKVM.Internal.JVM.IsUnix)
|
||||
{
|
||||
return new string[] { arg };
|
||||
}
|
||||
try
|
||||
{
|
||||
string dir = Path.GetDirectoryName(arg);
|
||||
|
@ -77,14 +73,7 @@ namespace IKVM.Runtime
|
|||
|
||||
public static string[] Glob()
|
||||
{
|
||||
if(IKVM.Internal.JVM.IsUnix)
|
||||
{
|
||||
return Environment.GetCommandLineArgs();
|
||||
}
|
||||
else
|
||||
{
|
||||
return Glob(1);
|
||||
}
|
||||
return Glob(1);
|
||||
}
|
||||
|
||||
public static string[] Glob(int skip)
|
||||
|
@ -163,7 +152,13 @@ namespace IKVM.Runtime
|
|||
{
|
||||
if(Thread.CurrentThread.Name == null)
|
||||
{
|
||||
Thread.CurrentThread.Name = "main";
|
||||
try
|
||||
{
|
||||
Thread.CurrentThread.Name = "main";
|
||||
}
|
||||
catch(InvalidOperationException)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -172,17 +167,9 @@ namespace IKVM.Runtime
|
|||
// FXBUG when the main thread ends, it doesn't actually die, it stays around to manage the lifetime
|
||||
// of the CLR, but in doing so it also keeps alive the thread local storage for this thread and we
|
||||
// use the TLS as a hack to track when the thread dies (if the object stored in the TLS is finalized,
|
||||
// we know the thread is dead). So to make that work for the main thread, we explicitly clear the TLS
|
||||
// slot that contains our hack object.
|
||||
try
|
||||
{
|
||||
Thread.SetData(Thread.GetNamedDataSlot("ikvm-thread-hack"), null);
|
||||
}
|
||||
catch(NullReferenceException)
|
||||
{
|
||||
// MONOBUG Thread.SetData throws a NullReferenceException on Mono
|
||||
// if the slot hadn't already been allocated
|
||||
}
|
||||
// we know the thread is dead). So to make that work for the main thread, we use jniDetach which
|
||||
// explicitly cleans up our thread.
|
||||
IKVM.Internal.JVM.Library.jniDetach();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -296,6 +283,7 @@ namespace IKVM.Internal
|
|||
private static bool noJniStubs;
|
||||
private static bool isStaticCompiler;
|
||||
private static bool noStackTraceInfo;
|
||||
private static bool isTlsEnabled;
|
||||
private static bool compilationPhase1;
|
||||
private static string sourcePath;
|
||||
private static bool monoBugWorkaround;
|
||||
|
@ -381,6 +369,18 @@ namespace IKVM.Internal
|
|||
}
|
||||
}
|
||||
|
||||
internal static bool IsTlsEnabled
|
||||
{
|
||||
get
|
||||
{
|
||||
return isTlsEnabled;
|
||||
}
|
||||
set
|
||||
{
|
||||
isTlsEnabled = value;
|
||||
}
|
||||
}
|
||||
|
||||
internal static bool CompileInnerClassesAsNestedTypes
|
||||
{
|
||||
get
|
||||
|
@ -1948,6 +1948,7 @@ namespace IKVM.Internal
|
|||
public bool nostacktraceinfo;
|
||||
public bool removeUnusedFields;
|
||||
public bool monoBugWorkaround;
|
||||
public bool enableTls;
|
||||
}
|
||||
|
||||
public static int Compile(CompilerOptions options)
|
||||
|
@ -1957,6 +1958,7 @@ namespace IKVM.Internal
|
|||
noJniStubs = options.nojni;
|
||||
noStackTraceInfo = options.nostacktraceinfo;
|
||||
monoBugWorkaround = options.monoBugWorkaround;
|
||||
isTlsEnabled = options.enableTls;
|
||||
foreach(string r in options.references)
|
||||
{
|
||||
try
|
||||
|
|
Загрузка…
Ссылка в новой задаче