diff options
author | jfrijters <jfrijters> | 2011-12-09 19:59:35 +0400 |
---|---|---|
committer | jfrijters <jfrijters> | 2011-12-09 19:59:35 +0400 |
commit | 140b448b5c67356e8dbb8358fedfe9e8113ee10f (patch) | |
tree | 1c663ca9a9f10e9c837310936fbff1d8ce803788 | |
parent | a86ccf30d5e7f9deebb40f9f9e5a09ab163380ca (diff) |
Moved AtomicReferenceFieldUpdater creation into FinishContext, to be able to better keep track of the types and avoid the global dictionary.
-rw-r--r-- | runtime/DynamicTypeWrapper.cs | 31 | ||||
-rw-r--r-- | runtime/atomic.cs | 51 |
2 files changed, 40 insertions, 42 deletions
diff --git a/runtime/DynamicTypeWrapper.cs b/runtime/DynamicTypeWrapper.cs index ebbc8716..9401dd55 100644 --- a/runtime/DynamicTypeWrapper.cs +++ b/runtime/DynamicTypeWrapper.cs @@ -3545,6 +3545,7 @@ namespace IKVM.Internal private List<System.Threading.ThreadStart> postFinishProcs; private List<Item> items; private int uniqueId; + private Dictionary<FieldWrapper, ConstructorBuilder> arfuMap; private struct Item { @@ -5380,6 +5381,36 @@ namespace IKVM.Internal }); return cb; } + + internal ConstructorBuilder GetAtomicReferenceFieldUpdater(FieldWrapper field) + { + if (arfuMap == null) + { + arfuMap = new Dictionary<FieldWrapper, ConstructorBuilder>(); + } + ConstructorBuilder cb; + if (!arfuMap.TryGetValue(field, out cb)) + { + TypeWrapper arfuTypeWrapper = ClassLoaderWrapper.LoadClassCritical("ikvm.internal.IntrinsicAtomicReferenceFieldUpdater"); + TypeBuilder tb = typeBuilder.DefineNestedType("__<ARFU>_" + (uniqueId++), TypeAttributes.NestedPrivate | TypeAttributes.Sealed, arfuTypeWrapper.TypeAsBaseType); + AtomicReferenceFieldUpdaterEmitter.EmitImpl(tb, field.GetField()); + cb = tb.DefineConstructor(MethodAttributes.Assembly, CallingConventions.Standard, Type.EmptyTypes); + arfuMap.Add(field, cb); + CodeEmitter ctorilgen = CodeEmitter.Create(cb); + ctorilgen.Emit(OpCodes.Ldarg_0); + MethodWrapper basector = arfuTypeWrapper.GetMethodWrapper("<init>", "()V", false); + basector.Link(); + basector.EmitCall(ctorilgen); + ctorilgen.Emit(OpCodes.Ret); + ctorilgen.DoEmit(); + RegisterPostFinishProc(delegate + { + arfuTypeWrapper.Finish(); + tb.CreateType(); + }); + } + return cb; + } } private static bool CheckRequireOverrideStub(MethodWrapper mw1, MethodWrapper mw2) diff --git a/runtime/atomic.cs b/runtime/atomic.cs index 91c3b971..b15ef0ca 100644 --- a/runtime/atomic.cs +++ b/runtime/atomic.cs @@ -1,5 +1,5 @@ /* - Copyright (C) 2007 Jeroen Frijters + Copyright (C) 2007-2011 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 @@ -37,8 +37,6 @@ using InstructionFlags = IKVM.Internal.ClassFile.Method.InstructionFlags; static class AtomicReferenceFieldUpdaterEmitter { - private static readonly Dictionary<FieldWrapper, ConstructorBuilder> map = new Dictionary<FieldWrapper, ConstructorBuilder>(); - internal static bool Emit(DynamicTypeWrapper.FinishContext context, TypeWrapper wrapper, CodeEmitter ilgen, ClassFile classFile, int i, ClassFile.Method.Instruction[] code, InstructionFlags[] flags) { if (i >= 3 @@ -60,7 +58,10 @@ static class AtomicReferenceFieldUpdaterEmitter if (field != null && !field.IsStatic && field.IsVolatile && field.DeclaringType == wrapper && field.FieldTypeWrapper == vclass) { // everything matches up, now call the actual emitter - DoEmit(context, wrapper, ilgen, field); + ilgen.Emit(OpCodes.Pop); + ilgen.Emit(OpCodes.Pop); + ilgen.Emit(OpCodes.Pop); + ilgen.Emit(OpCodes.Newobj, context.GetAtomicReferenceFieldUpdater(field)); return true; } } @@ -68,45 +69,11 @@ static class AtomicReferenceFieldUpdaterEmitter return false; } - private static void DoEmit(DynamicTypeWrapper.FinishContext context, TypeWrapper wrapper, CodeEmitter ilgen, FieldWrapper field) + internal static void EmitImpl(TypeBuilder tb, FieldInfo field) { - ConstructorBuilder cb; - bool exists; - lock (map) - { - exists = map.TryGetValue(field, out cb); - } - if (!exists) - { - // note that we don't need to lock here, because we're running as part of FinishCore, which is already protected by a lock - TypeWrapper arfuTypeWrapper = ClassLoaderWrapper.LoadClassCritical("ikvm.internal.IntrinsicAtomicReferenceFieldUpdater"); - TypeBuilder tb = wrapper.TypeAsBuilder.DefineNestedType("__<ARFU>_" + field.Name + field.Signature.Replace('.', '/'), TypeAttributes.NestedPrivate | TypeAttributes.Sealed, arfuTypeWrapper.TypeAsBaseType); - EmitCompareAndSet("compareAndSet", tb, field.GetField()); - EmitGet(tb, field.GetField()); - EmitSet("set", tb, field.GetField()); - - cb = tb.DefineConstructor(MethodAttributes.Assembly, CallingConventions.Standard, Type.EmptyTypes); - lock (map) - { - map.Add(field, cb); - } - CodeEmitter ctorilgen = CodeEmitter.Create(cb); - ctorilgen.Emit(OpCodes.Ldarg_0); - MethodWrapper basector = arfuTypeWrapper.GetMethodWrapper("<init>", "()V", false); - basector.Link(); - basector.EmitCall(ctorilgen); - ctorilgen.Emit(OpCodes.Ret); - ctorilgen.DoEmit(); - context.RegisterPostFinishProc(delegate - { - arfuTypeWrapper.Finish(); - tb.CreateType(); - }); - } - ilgen.Emit(OpCodes.Pop); - ilgen.Emit(OpCodes.Pop); - ilgen.Emit(OpCodes.Pop); - ilgen.Emit(OpCodes.Newobj, cb); + EmitCompareAndSet("compareAndSet", tb, field); + EmitGet(tb, field); + EmitSet("set", tb, field); } private static void EmitCompareAndSet(string name, TypeBuilder tb, FieldInfo field) |