зеркало из https://github.com/mono/ikvm-fork.git
Intrinsified ThreadLocal (under specific circumstances).
This commit is contained in:
Родитель
ff779a78f7
Коммит
0751ab4d76
|
@ -40,6 +40,7 @@ ikvm/awt/IkvmToolkit.java
|
|||
ikvm/internal/AnnotationAttributeBase.java
|
||||
ikvm/internal/FieldReflectorBase.java
|
||||
ikvm/internal/IntrinsicAtomicReferenceFieldUpdater.java
|
||||
ikvm/internal/IntrinsicThreadLocal.java
|
||||
ikvm/internal/Serialization.java
|
||||
java/awt/Font.java
|
||||
java/awt/GraphicsConfiguration.java
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
Copyright (C) 2010 Jeroen Frijters
|
||||
|
||||
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
|
||||
|
||||
*/
|
||||
package ikvm.internal;
|
||||
|
||||
// This is the base class for intrinsified ThreadLocals, it's main purpose
|
||||
// is to avoid having to add a remove() method to every generated class,
|
||||
// but it also gives us some maneuvering room should a future JDK version
|
||||
// change ThreadLocal.
|
||||
// Note that because this class is abstract, getClass() on an intrinsified
|
||||
// ThreadLocal instance will return java.lang.ThreadLocal instead of this class.
|
||||
// We don't use HideFromJava for this, because that would make the life of
|
||||
// the runtime/ikvmc more difficult (because it needs a TypeWrapper for this class).
|
||||
|
||||
public abstract class IntrinsicThreadLocal extends ThreadLocal
|
||||
{
|
||||
public final void remove()
|
||||
{
|
||||
set(null);
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright (C) 2008, 2009 Jeroen Frijters
|
||||
Copyright (C) 2008-2010 Jeroen Frijters
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
@ -106,6 +106,7 @@ namespace IKVM.Internal
|
|||
// this only applies to the core class library, so makes no sense in dynamic mode
|
||||
intrinsics.Add(new IntrinsicKey("java.lang.Class", "getPrimitiveClass", "(Ljava.lang.String;)Ljava.lang.Class;"), Class_getPrimitiveClass);
|
||||
#endif
|
||||
intrinsics.Add(new IntrinsicKey("java.lang.ThreadLocal", "<init>", "()V"), ThreadLocal_new);
|
||||
return intrinsics;
|
||||
}
|
||||
|
||||
|
@ -418,5 +419,54 @@ namespace IKVM.Internal
|
|||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
private static bool ThreadLocal_new(DynamicTypeWrapper.FinishContext context, CodeEmitter ilgen, MethodWrapper method, MethodAnalyzer ma, int opcodeIndex, MethodWrapper caller, ClassFile classFile, ClassFile.Method.Instruction[] code)
|
||||
{
|
||||
// it is only valid to replace a ThreadLocal instantiation by our ThreadStatic based version, if we can prove that the instantiation only happens once
|
||||
// (which is the case when we're in <clinit> and there aren't any branches that lead to the current position)
|
||||
if (caller.Name != StringConstants.CLINIT)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i <= opcodeIndex; i++)
|
||||
{
|
||||
if (code[i].IsBranchTarget)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
ilgen.Emit(OpCodes.Newobj, DefineThreadLocalType(context, opcodeIndex, caller));
|
||||
return true;
|
||||
}
|
||||
|
||||
private static ConstructorBuilder DefineThreadLocalType(DynamicTypeWrapper.FinishContext context, int opcodeIndex, MethodWrapper caller)
|
||||
{
|
||||
TypeWrapper threadLocal = ClassLoaderWrapper.LoadClassCritical("ikvm.internal.IntrinsicThreadLocal");
|
||||
TypeBuilder tb = caller.DeclaringType.TypeAsBuilder.DefineNestedType("__<tls>_" + opcodeIndex, TypeAttributes.NestedPrivate | TypeAttributes.Sealed, threadLocal.TypeAsBaseType);
|
||||
FieldBuilder fb = tb.DefineField("field", Types.Object, FieldAttributes.Private | FieldAttributes.Static);
|
||||
fb.SetCustomAttribute(new CustomAttributeBuilder(JVM.Import(typeof(ThreadStaticAttribute)).GetConstructor(Type.EmptyTypes), new object[0]));
|
||||
MethodBuilder mbGet = tb.DefineMethod("get", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.Final, Types.Object, Type.EmptyTypes);
|
||||
ILGenerator ilgen = mbGet.GetILGenerator();
|
||||
ilgen.Emit(OpCodes.Ldsfld, fb);
|
||||
ilgen.Emit(OpCodes.Ret);
|
||||
MethodBuilder mbSet = tb.DefineMethod("set", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.Final, null, new Type[] { Types.Object });
|
||||
ilgen = mbSet.GetILGenerator();
|
||||
ilgen.Emit(OpCodes.Ldarg_1);
|
||||
ilgen.Emit(OpCodes.Stsfld, fb);
|
||||
ilgen.Emit(OpCodes.Ret);
|
||||
ConstructorBuilder cb = tb.DefineConstructor(MethodAttributes.Assembly, CallingConventions.Standard, Type.EmptyTypes);
|
||||
CodeEmitter ctorilgen = CodeEmitter.Create(cb);
|
||||
ctorilgen.Emit(OpCodes.Ldarg_0);
|
||||
MethodWrapper basector = threadLocal.GetMethodWrapper("<init>", "()V", false);
|
||||
basector.Link();
|
||||
basector.EmitCall(ctorilgen);
|
||||
ctorilgen.Emit(OpCodes.Ret);
|
||||
context.RegisterPostFinishProc(delegate
|
||||
{
|
||||
threadLocal.Finish();
|
||||
tb.CreateType();
|
||||
});
|
||||
return cb;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче