2
Copyright (C) 2002-2012 Jeroen Frijters
4
This software is provided 'as-is', without any express or implied
5
warranty. In no event will the authors be held liable for any damages
6
arising from the use of this software.
8
Permission is granted to anyone to use this software for any purpose,
9
including commercial applications, and to alter it and redistribute it
10
freely, subject to the following restrictions:
12
1. The origin of this software must not be misrepresented; you must not
13
claim that you wrote the original software. If you use this software
14
in a product, an acknowledgment in the product documentation would be
15
appreciated but is not required.
16
2. Altered source versions must be plainly marked as such, and must not be
17
misrepresented as being the original software.
18
3. This notice may not be removed or altered from any source distribution.
25
using System.Collections.Generic;
27
using IKVM.Reflection;
28
using IKVM.Reflection.Emit;
29
using Type = IKVM.Reflection.Type;
30
using DynamicOrAotTypeWrapper = IKVM.Internal.AotTypeWrapper;
32
using System.Reflection;
33
using System.Reflection.Emit;
34
using DynamicOrAotTypeWrapper = IKVM.Internal.DynamicTypeWrapper;
36
using System.Diagnostics;
37
using System.Security;
38
using System.Security.Permissions;
39
using IKVM.Attributes;
41
namespace IKVM.Internal
44
abstract class DynamicTypeWrapper : TypeWrapper
46
class DynamicTypeWrapper : TypeWrapper
50
protected readonly CompilerClassLoader classLoader;
52
protected readonly ClassLoaderWrapper classLoader;
54
private volatile DynamicImpl impl;
55
private readonly TypeWrapper baseTypeWrapper;
56
private TypeWrapper[] interfaces;
57
private readonly string sourceFileName;
59
private byte[][] lineNumberTables;
61
private MethodBase automagicSerializationCtor;
63
private static TypeWrapper LoadTypeWrapper(ClassLoaderWrapper classLoader, string name)
65
TypeWrapper tw = classLoader.LoadClassByDottedNameFast(name);
68
throw new NoClassDefFoundError(name);
74
internal DynamicTypeWrapper(ClassFile f, CompilerClassLoader classLoader)
76
internal DynamicTypeWrapper(ClassFile f, ClassLoaderWrapper classLoader)
78
: base(f.Modifiers, f.Name)
80
Profiler.Count("DynamicTypeWrapper");
81
this.classLoader = classLoader;
82
this.IsInternal = f.IsInternal;
83
this.sourceFileName = f.SourceFileAttribute;
84
this.baseTypeWrapper = f.IsInterface ? null : LoadTypeWrapper(classLoader, f.SuperClass);
85
if (BaseTypeWrapper != null)
87
if (!BaseTypeWrapper.IsAccessibleFrom(this))
89
throw new IllegalAccessError("Class " + f.Name + " cannot access its superclass " + BaseTypeWrapper.Name);
92
if (!BaseTypeWrapper.IsPublic && !ReflectUtil.IsFromAssembly(BaseTypeWrapper.TypeAsBaseType, classLoader.GetTypeWrapperFactory().ModuleBuilder.Assembly))
94
// NOTE this can only happen if evil code calls ClassLoader.defineClass() on an assembly class loader (which we allow for compatibility with other slightly less evil code)
95
throw new IllegalAccessError("Class " + f.Name + " cannot access its non-public superclass " + BaseTypeWrapper.Name + " from another assembly");
98
if (BaseTypeWrapper.IsFinal)
100
throw new VerifyError("Class " + f.Name + " extends final class " + BaseTypeWrapper.Name);
102
if (BaseTypeWrapper.IsInterface)
104
throw new IncompatibleClassChangeError("Class " + f.Name + " has interface " + BaseTypeWrapper.Name + " as superclass");
106
if (BaseTypeWrapper.TypeAsTBD == Types.Delegate)
108
throw new VerifyError(BaseTypeWrapper.Name + " cannot be used as a base class");
110
// NOTE defining value types, enums is not supported in IKVM v1
111
if (BaseTypeWrapper.TypeAsTBD == Types.ValueType || BaseTypeWrapper.TypeAsTBD == Types.Enum)
113
throw new VerifyError("Defining value types in Java is not implemented in IKVM v1");
120
if (JVM.classUnloading && BaseTypeWrapper.TypeAsBaseType == typeof(ContextBoundObject))
122
throw new VerifyError("Extending ContextBoundObject is not supported in dynamic mode with class GC enabled.");
128
if (JVM.classUnloading)
130
VerifyRunAndCollect(f);
134
ClassFile.ConstantPoolItemClass[] interfaces = f.Interfaces;
135
this.interfaces = new TypeWrapper[interfaces.Length];
136
for (int i = 0; i < interfaces.Length; i++)
138
TypeWrapper iface = LoadTypeWrapper(classLoader, interfaces[i].Name);
139
if (!iface.IsAccessibleFrom(this))
141
throw new IllegalAccessError("Class " + f.Name + " cannot access its superinterface " + iface.Name);
144
if (!iface.IsPublic && !ReflectUtil.IsFromAssembly(iface.TypeAsBaseType, classLoader.GetTypeWrapperFactory().ModuleBuilder.Assembly))
146
string proxyName = DynamicClassLoader.GetProxyHelperName(iface.TypeAsTBD);
147
Type proxyType = ReflectUtil.GetAssembly(iface.TypeAsBaseType).GetType(proxyName);
148
// FXBUG we need to check if the type returned is actually correct, because .NET 2.0 has a bug that
149
// causes it to return typeof(IFoo) for GetType("__<Proxy>+IFoo")
150
if (proxyType == null || proxyType.FullName != proxyName)
152
// NOTE this happens when you call Proxy.newProxyInstance() on a non-public .NET interface
153
// (for ikvmc compiled Java types, ikvmc generates public proxy stubs).
154
// NOTE we don't currently check interfaces inherited from other interfaces because mainstream .NET languages
155
// don't allow public interfaces extending non-public interfaces.
156
throw new IllegalAccessError("Class " + f.Name + " cannot access its non-public superinterface " + iface.Name + " from another assembly");
160
if (!iface.IsInterface)
162
throw new IncompatibleClassChangeError("Implementing class");
164
this.interfaces[i] = iface;
167
impl = new JavaTypeImpl(f, this);
171
private static void VerifyRunAndCollect(ClassFile f)
173
if (f.Annotations != null)
175
foreach (object[] ann in f.Annotations)
177
if (ann[1].Equals("Lcli/System/Runtime/InteropServices/ComImportAttribute$Annotation;"))
179
throw new VerifyError("ComImportAttribute is not supported in dynamic mode with class GC enabled.");
183
foreach (ClassFile.Field field in f.Fields)
185
if (field.Annotations != null)
187
foreach (object[] ann in field.Annotations)
189
if (ann[1].Equals("Lcli/System/ThreadStaticAttribute$Annotation;"))
191
throw new VerifyError("ThreadStaticAttribute is not supported in dynamic mode with class GC enabled.");
193
if (ann[1].Equals("Lcli/System/ContextStaticAttribute$Annotation;"))
195
throw new VerifyError("ContextStaticAttribute is not supported in dynamic mode with class GC enabled.");
200
foreach (ClassFile.Method method in f.Methods)
202
if (method.Annotations != null)
204
foreach (object[] ann in method.Annotations)
206
if (ann[1].Equals("Lcli/System/Runtime/InteropServices/DllImportAttribute$Annotation;"))
208
throw new VerifyError("DllImportAttribute is not supported in dynamic mode with class GC enabled.");
216
private void VerifyDelegate(ClassFile f)
220
throw new VerifyError("Delegate must be final");
222
ClassFile.Method invoke = null;
223
ClassFile.Method beginInvoke = null;
224
ClassFile.Method endInvoke = null;
225
ClassFile.Method constructor = null;
226
foreach (ClassFile.Method m in f.Methods)
228
if (m.Name == "Invoke")
232
throw new VerifyError("Delegate may only have a single Invoke method");
236
else if (m.Name == "BeginInvoke")
238
if (beginInvoke != null)
240
throw new VerifyError("Delegate may only have a single BeginInvoke method");
244
else if (m.Name == "EndInvoke")
246
if (endInvoke != null)
248
throw new VerifyError("Delegate may only have a single EndInvoke method");
252
else if (m.Name == "<init>")
254
if (constructor != null)
256
throw new VerifyError("Delegate may only have a single constructor");
262
throw new VerifyError("Delegate may not have any native methods besides Invoke, BeginInvoke and EndInvoke");
265
if (invoke == null || constructor == null)
267
throw new VerifyError("Delegate must have a constructor and an Invoke method");
269
if (!invoke.IsPublic || !invoke.IsNative || invoke.IsFinal || invoke.IsStatic)
271
throw new VerifyError("Delegate Invoke method must be a public native non-final instance method");
273
if ((beginInvoke != null && endInvoke == null) || (beginInvoke == null && endInvoke != null))
275
throw new VerifyError("Delegate must have both BeginInvoke and EndInvoke or neither");
277
if (!constructor.IsPublic)
279
throw new VerifyError("Delegate constructor must be public");
281
if (constructor.Instructions.Length < 3
282
|| constructor.Instructions[0].NormalizedOpCode != NormalizedByteCode.__aload
283
|| constructor.Instructions[0].NormalizedArg1 != 0
284
|| constructor.Instructions[1].NormalizedOpCode != NormalizedByteCode.__invokespecial
285
|| constructor.Instructions[2].NormalizedOpCode != NormalizedByteCode.__return)
287
throw new VerifyError("Delegate constructor must be empty");
289
if (f.Fields.Length != 0)
291
throw new VerifyError("Delegate may not declare any fields");
293
TypeWrapper iface = classLoader.LoadClassByDottedNameFast(f.Name + DotNetTypeWrapper.DelegateInterfaceSuffix);
294
DelegateInnerClassCheck(iface != null);
295
DelegateInnerClassCheck(iface.IsInterface);
296
DelegateInnerClassCheck(iface.IsPublic);
297
DelegateInnerClassCheck(iface.GetClassLoader() == classLoader);
298
MethodWrapper[] methods = iface.GetMethods();
299
DelegateInnerClassCheck(methods.Length == 1 && methods[0].Name == "Invoke");
300
if (methods[0].Signature != invoke.Signature)
302
throw new VerifyError("Delegate Invoke method signature must be identical to inner interface Invoke method signature");
304
if (iface.Interfaces.Length != 0)
306
throw new VerifyError("Delegate inner interface may not extend any interfaces");
308
if (constructor.Signature != "(" + iface.SigName + ")V")
310
throw new VerifyError("Delegate constructor must take a single argument of type inner Method interface");
312
if (beginInvoke != null && beginInvoke.Signature != invoke.Signature.Substring(0, invoke.Signature.IndexOf(')')) + "Lcli.System.AsyncCallback;Ljava.lang.Object;)Lcli.System.IAsyncResult;")
314
throw new VerifyError("Delegate BeginInvoke method has incorrect signature");
316
if (endInvoke != null && endInvoke.Signature != "(Lcli.System.IAsyncResult;)" + invoke.Signature.Substring(invoke.Signature.IndexOf(')') + 1))
318
throw new VerifyError("Delegate EndInvoke method has incorrect signature");
322
private static void DelegateInnerClassCheck(bool cond)
326
throw new VerifyError("Delegate must have a public inner interface named Method with a single method named Invoke");
330
private bool IsDelegate
334
TypeWrapper baseTypeWrapper = BaseTypeWrapper;
335
return baseTypeWrapper != null && baseTypeWrapper.TypeAsTBD == Types.MulticastDelegate;
339
internal sealed override TypeWrapper BaseTypeWrapper
341
get { return baseTypeWrapper; }
344
internal override ClassLoaderWrapper GetClassLoader()
349
internal override Modifiers ReflectiveModifiers
353
return impl.ReflectiveModifiers;
357
internal override TypeWrapper[] Interfaces
365
internal override TypeWrapper[] InnerClasses
369
return impl.InnerClasses;
373
internal override TypeWrapper DeclaringTypeWrapper
377
return impl.DeclaringTypeWrapper;
381
internal override Type TypeAsTBD
389
internal override void Finish()
391
// we don't need locking, because Finish is Thread safe
392
impl = impl.Finish();
395
internal void CreateStep1()
397
((JavaTypeImpl)impl).CreateStep1();
400
internal void CreateStep2()
402
((JavaTypeImpl)impl).CreateStep2();
405
private bool IsSerializable
409
return this.IsSubTypeOf(ClassLoaderWrapper.LoadClassCritical("java.io.Serializable"));
413
private abstract class DynamicImpl
415
internal abstract Type Type { get; }
416
internal abstract TypeWrapper[] InnerClasses { get; }
417
internal abstract TypeWrapper DeclaringTypeWrapper { get; }
418
internal abstract Modifiers ReflectiveModifiers { get; }
419
internal abstract DynamicImpl Finish();
420
internal abstract MethodBase LinkMethod(MethodWrapper mw);
421
internal abstract FieldInfo LinkField(FieldWrapper fw);
422
internal abstract void EmitRunClassConstructor(CodeEmitter ilgen);
423
internal abstract string GetGenericSignature();
424
internal abstract string[] GetEnclosingMethod();
425
internal abstract string GetGenericMethodSignature(int index);
426
internal abstract string GetGenericFieldSignature(int index);
427
internal abstract object[] GetDeclaredAnnotations();
428
internal abstract object GetMethodDefaultValue(int index);
429
internal abstract object[] GetMethodAnnotations(int index);
430
internal abstract object[][] GetParameterAnnotations(int index);
431
internal abstract object[] GetFieldAnnotations(int index);
432
internal abstract MethodInfo GetFinalizeMethod();
435
private sealed class JavaTypeImpl : DynamicImpl
437
private readonly ClassFile classFile;
438
private readonly DynamicOrAotTypeWrapper wrapper;
439
private TypeBuilder typeBuilder;
440
private MethodWrapper[] methods;
441
private MethodWrapper[][] baseMethods;
442
private FieldWrapper[] fields;
443
private FinishedTypeImpl finishedType;
444
private bool finishInProgress;
445
private MethodBuilder clinitMethod;
446
private MethodBuilder finalizeMethod;
448
private DynamicTypeWrapper outerClassWrapper;
449
private AnnotationBuilder annotationBuilder;
450
private TypeBuilder enumBuilder;
451
private Dictionary<string, TypeWrapper> nestedTypeNames; // only keys are used, values are always null
454
internal JavaTypeImpl(ClassFile f, DynamicTypeWrapper wrapper)
456
Tracer.Info(Tracer.Compiler, "constructing JavaTypeImpl for " + f.Name);
458
this.wrapper = (DynamicOrAotTypeWrapper)wrapper;
461
internal void CreateStep1()
463
// process all methods
464
bool hasclinit = wrapper.BaseTypeWrapper == null ? false : wrapper.BaseTypeWrapper.HasStaticInitializer;
465
methods = new MethodWrapper[classFile.Methods.Length];
466
baseMethods = new MethodWrapper[classFile.Methods.Length][];
467
for (int i = 0; i < methods.Length; i++)
469
ClassFile.Method m = classFile.Methods[i];
470
if (m.IsClassInitializer)
474
if (IsSideEffectFreeStaticInitializerOrNoop(m, out noop))
476
// because we cannot affect serialVersionUID computation (which is the only way the presence of a <clinit> can surface)
477
// we cannot do this optimization if the class is serializable but doesn't have a serialVersionUID
478
if (noop && (!wrapper.IsSerializable || classFile.HasSerialVersionUID))
480
methods[i] = new DummyMethodWrapper(wrapper);
492
MemberFlags flags = MemberFlags.None;
495
flags |= MemberFlags.InternalAccess;
497
// we only support HasCallerID instance methods on final types, because we don't support interface stubs with CallerID
498
if (m.HasCallerIDAnnotation
499
&& (m.IsStatic || classFile.IsFinal)
500
&& CoreClasses.java.lang.Object.Wrapper.InternalsVisibleTo(wrapper))
502
flags |= MemberFlags.CallerID;
506
methods[i] = new GhostMethodWrapper(wrapper, m.Name, m.Signature, null, null, null, null, m.Modifiers, flags);
508
else if (m.IsConstructor && wrapper.IsDelegate)
510
methods[i] = new DelegateConstructorMethodWrapper(wrapper, m);
514
if (!classFile.IsInterface && !m.IsStatic && !m.IsPrivate && !m.IsConstructor)
516
bool explicitOverride = false;
517
baseMethods[i] = FindBaseMethods(m, out explicitOverride);
518
if (explicitOverride)
520
flags |= MemberFlags.ExplicitOverride;
523
methods[i] = new TypicalMethodWrapper(wrapper, m.Name, m.Signature, null, null, null, m.Modifiers, flags);
526
wrapper.HasStaticInitializer = hasclinit;
527
if (wrapper.IsAbstract && (!wrapper.IsInterface || wrapper.IsPublic))
529
List<MethodWrapper> methodsArray = new List<MethodWrapper>(methods);
530
List<MethodWrapper[]> baseMethodsArray = new List<MethodWrapper[]>(baseMethods);
531
AddMirandaMethods(methodsArray, baseMethodsArray, wrapper);
532
methods = methodsArray.ToArray();
533
baseMethods = baseMethodsArray.ToArray();
535
if (!wrapper.IsInterface)
537
AddDelegateInvokeStubs(wrapper, ref methods);
539
wrapper.SetMethods(methods);
541
fields = new FieldWrapper[classFile.Fields.Length];
542
for (int i = 0; i < fields.Length; i++)
544
ClassFile.Field fld = classFile.Fields[i];
545
if (fld.IsStaticFinalConstant)
547
TypeWrapper fieldType = null;
549
fieldType = ClassLoaderWrapper.GetBootstrapClassLoader().FieldTypeWrapperFromSig(fld.Signature);
551
fields[i] = new ConstantFieldWrapper(wrapper, fieldType, fld.Name, fld.Signature, fld.Modifiers, null, fld.ConstantValue, MemberFlags.None);
553
else if (fld.IsProperty)
555
fields[i] = new DynamicPropertyFieldWrapper(wrapper, fld);
559
fields[i] = FieldWrapper.Create(wrapper, null, null, fld.Name, fld.Signature, new ExModifiers(fld.Modifiers, fld.IsInternal));
563
wrapper.AddMapXmlFields(ref fields);
565
wrapper.SetFields(fields);
568
internal void CreateStep2()
571
if (typeBuilder != null)
573
// in the static compiler we need to create the TypeBuilder from outer to inner
574
// and to avoid having to sort the classes this way, we instead call CreateStep2
575
// on demand for outer wrappers and this necessitates us to keep track of
576
// whether we've already been called
580
// this method is not allowed to throw exceptions (if it does, the runtime will abort)
581
bool hasclinit = wrapper.HasStaticInitializer;
582
string mangledTypeName = wrapper.classLoader.GetTypeWrapperFactory().AllocMangledName(wrapper);
583
ClassFile f = classFile;
586
TypeAttributes typeAttribs = 0;
589
typeAttribs |= TypeAttributes.Abstract;
593
typeAttribs |= TypeAttributes.Sealed;
597
typeAttribs |= TypeAttributes.BeforeFieldInit;
600
bool cantNest = false;
601
bool setModifiers = false;
602
TypeBuilder outer = null;
603
// we only compile inner classes as nested types in the static compiler, because it has a higher cost
604
// and doesn't buy us anything in dynamic mode (and if fact, due to an FXBUG it would make handling
605
// the TypeResolve event very hard)
606
ClassFile.InnerClass outerClass = getOuterClass();
607
if (outerClass.outerClass != 0)
609
string outerClassName = classFile.GetConstantPoolClass(outerClass.outerClass);
610
if (!CheckInnerOuterNames(f.Name, outerClassName))
612
Tracer.Warning(Tracer.Compiler, "Incorrect InnerClasses attribute on {0}", f.Name);
618
outerClassWrapper = wrapper.classLoader.LoadClassByDottedNameFast(outerClassName) as DynamicTypeWrapper;
620
catch (RetargetableJavaException x)
622
Tracer.Warning(Tracer.Compiler, "Unable to load outer class {0} for inner class {1} ({2}: {3})", outerClassName, f.Name, x.GetType().Name, x.Message);
624
if (outerClassWrapper != null)
626
// make sure the relationship is reciprocal (otherwise we run the risk of
627
// baking the outer type before the inner type) and that the inner and outer
628
// class live in the same class loader (when doing a multi target compilation,
629
// it is possible to split the two classes acros assemblies)
630
JavaTypeImpl oimpl = outerClassWrapper.impl as JavaTypeImpl;
631
if (oimpl != null && outerClassWrapper.GetClassLoader() == wrapper.GetClassLoader())
633
ClassFile outerClassFile = oimpl.classFile;
634
ClassFile.InnerClass[] outerInnerClasses = outerClassFile.InnerClasses;
635
if (outerInnerClasses == null)
637
outerClassWrapper = null;
642
for (int i = 0; i < outerInnerClasses.Length; i++)
644
if (outerInnerClasses[i].outerClass != 0
645
&& outerClassFile.GetConstantPoolClass(outerInnerClasses[i].outerClass) == outerClassFile.Name
646
&& outerInnerClasses[i].innerClass != 0
647
&& outerClassFile.GetConstantPoolClass(outerInnerClasses[i].innerClass) == f.Name)
655
outerClassWrapper = null;
661
outerClassWrapper = null;
663
if (outerClassWrapper != null)
665
outerClassWrapper.CreateStep2();
666
outer = oimpl.typeBuilder;
670
Tracer.Warning(Tracer.Compiler, "Non-reciprocal inner class {0}", f.Name);
679
if (outerClassWrapper.IsPublic)
681
typeAttribs |= TypeAttributes.NestedPublic;
685
// We're a public type nested inside a non-public type, this means that we can't compile this type as a nested type,
686
// because that would mean it wouldn't be visible outside the assembly.
688
typeAttribs |= TypeAttributes.Public;
693
typeAttribs |= TypeAttributes.Public;
696
else if (outer != null)
698
typeAttribs |= TypeAttributes.NestedAssembly;
700
#else // STATIC_COMPILER
703
typeAttribs |= TypeAttributes.Public;
705
#endif // STATIC_COMPILER
708
typeAttribs |= TypeAttributes.Interface | TypeAttributes.Abstract;
710
// if any "meaningless" bits are set, preserve them
711
setModifiers |= (f.Modifiers & (Modifiers)0x99CE) != 0;
712
// by default we assume interfaces are abstract, so in the exceptional case we need a ModifiersAttribute
713
setModifiers |= (f.Modifiers & Modifiers.Abstract) == 0;
714
if (outer != null && !cantNest)
718
// TODO this is low priority, since the current Java class library doesn't define any ghost interfaces
720
throw new NotImplementedException();
722
// LAMESPEC the CLI spec says interfaces cannot contain nested types (Part.II, 9.6), but that rule isn't enforced
723
// (and broken by J# as well), so we'll just ignore it too.
724
typeBuilder = outer.DefineNestedType(GetInnerClassName(outerClassWrapper.Name, f.Name), typeAttribs);
730
typeBuilder = wrapper.DefineGhostType(mangledTypeName, typeAttribs);
734
typeBuilder = wrapper.classLoader.GetTypeWrapperFactory().ModuleBuilder.DefineType(mangledTypeName, typeAttribs);
737
#else // STATIC_COMPILER
738
typeBuilder = wrapper.classLoader.GetTypeWrapperFactory().ModuleBuilder.DefineType(mangledTypeName, typeAttribs);
739
#endif // STATIC_COMPILER
743
typeAttribs |= TypeAttributes.Class;
745
// if any "meaningless" bits are set, preserve them
746
setModifiers |= (f.Modifiers & (Modifiers)0x99CE) != 0;
747
// by default we assume ACC_SUPER for classes, so in the exceptional case we need a ModifiersAttribute
748
setModifiers |= !f.IsSuper;
749
if (f.IsEffectivelyFinal)
752
typeAttribs |= TypeAttributes.Sealed;
753
Tracer.Info(Tracer.Compiler, "Sealing type {0}", f.Name);
755
if (outer != null && !cantNest)
757
// LAMESPEC the CLI spec says interfaces cannot contain nested types (Part.II, 9.6), but that rule isn't enforced
758
// (and broken by J# as well), so we'll just ignore it too.
759
typeBuilder = outer.DefineNestedType(GetInnerClassName(outerClassWrapper.Name, f.Name), typeAttribs);
762
#endif // STATIC_COMPILER
764
typeBuilder = wrapper.classLoader.GetTypeWrapperFactory().ModuleBuilder.DefineType(mangledTypeName, typeAttribs);
768
// When we're statically compiling, we associate the typeBuilder with the wrapper. This enables types in referenced assemblies to refer back to
769
// types that we're currently compiling (i.e. a cyclic dependency between the currently assembly we're compiling and a referenced assembly).
770
wrapper.GetClassLoader().SetWrapperForType(typeBuilder, wrapper);
771
if (outer != null && cantNest)
773
AttributeHelper.SetNonNestedOuterClass(typeBuilder, outerClassWrapper.Name);
774
AttributeHelper.SetNonNestedInnerClass(outer, f.Name);
776
if (outer == null && mangledTypeName != wrapper.Name)
778
// HACK we abuse the InnerClassAttribute to record to real name
779
AttributeHelper.SetInnerClass(typeBuilder, wrapper.Name, wrapper.Modifiers);
781
if (typeBuilder.FullName != wrapper.Name
782
&& wrapper.Name.Replace('$', '+') != typeBuilder.FullName)
784
wrapper.classLoader.AddNameMapping(wrapper.Name, typeBuilder.FullName);
786
if (f.IsAnnotation && Annotation.HasRetentionPolicyRuntime(f.Annotations))
788
annotationBuilder = new AnnotationBuilder(this, outer);
789
wrapper.SetAnnotation(annotationBuilder);
791
// For Java 5 Enum types, we generate a nested .NET enum.
792
// This is primarily to support annotations that take enum parameters.
793
if (f.IsEnum && f.IsPublic)
795
CompilerClassLoader ccl = wrapper.classLoader;
796
string name = "__Enum";
797
while (!ccl.ReserveName(f.Name + "$" + name))
801
enumBuilder = typeBuilder.DefineNestedType(name, TypeAttributes.Class | TypeAttributes.Sealed | TypeAttributes.NestedPublic | TypeAttributes.Serializable, Types.Enum);
802
AttributeHelper.HideFromJava(enumBuilder);
803
enumBuilder.DefineField("value__", Types.Int32, FieldAttributes.Public | FieldAttributes.SpecialName | FieldAttributes.RTSpecialName);
804
for (int i = 0; i < f.Fields.Length; i++)
806
if (f.Fields[i].IsEnum)
808
FieldBuilder fieldBuilder = enumBuilder.DefineField(f.Fields[i].Name, enumBuilder, FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.Literal);
809
fieldBuilder.SetConstant(i);
812
wrapper.SetEnumType(enumBuilder);
814
TypeWrapper[] interfaces = wrapper.Interfaces;
815
string[] implements = new string[interfaces.Length];
816
for (int i = 0; i < implements.Length; i++)
818
implements[i] = interfaces[i].Name;
822
Modifiers innerClassModifiers = outerClass.accessFlags;
823
string innerClassName = classFile.GetConstantPoolClass(outerClass.innerClass);
824
if (innerClassName == classFile.Name && innerClassName == outerClassWrapper.Name + "$" + typeBuilder.Name)
826
innerClassName = null;
828
AttributeHelper.SetInnerClass(typeBuilder, innerClassName, innerClassModifiers);
830
else if (outerClass.innerClass != 0)
832
AttributeHelper.SetInnerClass(typeBuilder, null, outerClass.accessFlags);
834
AttributeHelper.SetImplementsAttribute(typeBuilder, interfaces);
835
if (classFile.DeprecatedAttribute)
837
AttributeHelper.SetDeprecatedAttribute(typeBuilder);
839
if (classFile.GenericSignature != null)
841
AttributeHelper.SetSignatureAttribute(typeBuilder, classFile.GenericSignature);
843
if (classFile.EnclosingMethod != null)
845
AttributeHelper.SetEnclosingMethodAttribute(typeBuilder, classFile.EnclosingMethod[0], classFile.EnclosingMethod[1], classFile.EnclosingMethod[2]);
847
if (wrapper.classLoader.EmitStackTraceInfo)
849
if (f.SourceFileAttribute != null)
851
if (f.SourceFileAttribute != typeBuilder.Name + ".java")
853
AttributeHelper.SetSourceFile(typeBuilder, f.SourceFileAttribute);
858
AttributeHelper.SetSourceFile(typeBuilder, null);
861
// NOTE in Whidbey we can (and should) use CompilerGeneratedAttribute to mark Synthetic types
862
if (setModifiers || classFile.IsInternal || (classFile.Modifiers & (Modifiers.Synthetic | Modifiers.Annotation | Modifiers.Enum)) != 0)
864
AttributeHelper.SetModifiers(typeBuilder, classFile.Modifiers, classFile.IsInternal);
866
#endif // STATIC_COMPILER
869
// We create a empty method that we can use to trigger our .cctor
870
// (previously we used RuntimeHelpers.RunClassConstructor, but that is slow and requires additional privileges)
871
MethodAttributes attribs = MethodAttributes.Static | MethodAttributes.SpecialName;
872
if (classFile.IsAbstract)
874
bool hasfields = false;
875
// If we have any public static fields, the cctor trigger must (and may) be public as well
876
foreach (ClassFile.Field fld in classFile.Fields)
878
if (fld.IsPublic && fld.IsStatic)
884
attribs |= hasfields ? MethodAttributes.Public : MethodAttributes.FamORAssem;
888
attribs |= MethodAttributes.Public;
890
clinitMethod = typeBuilder.DefineMethod("__<clinit>", attribs, null, null);
891
clinitMethod.GetILGenerator().Emit(OpCodes.Ret);
892
// FXBUG on .NET 2.0 RTM x64 the JIT sometimes throws an InvalidProgramException while trying to inline this method,
893
// so we prevent inlining for now (it also turns out that on x86 not inlining this method actually has a positive perf impact in some cases...)
894
// http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=285772
895
clinitMethod.SetImplementationFlags(clinitMethod.GetMethodImplementationFlags() | MethodImplAttributes.NoInlining);
897
if (HasStructLayoutAttributeAnnotation(classFile))
899
// when we have a StructLayoutAttribute, field order is significant,
900
// so we link all fields here to make sure they are created in class file order.
901
foreach (FieldWrapper fw in fields)
912
JVM.CriticalFailure("Exception during JavaTypeImpl.CreateStep2", x);
917
private sealed class DelegateConstructorMethodWrapper : MethodWrapper
919
private MethodBuilder constructor;
920
private MethodInfo invoke;
922
internal DelegateConstructorMethodWrapper(DynamicTypeWrapper tw, ClassFile.Method m)
923
: base(tw, m.Name, m.Signature, null, null, null, m.Modifiers, MemberFlags.None)
927
internal void DoLink(TypeBuilder typeBuilder)
929
MethodAttributes attribs = MethodAttributes.HideBySig | MethodAttributes.Public;
930
constructor = ReflectUtil.DefineConstructor(typeBuilder, attribs, new Type[] { Types.Object, Types.IntPtr });
931
constructor.SetImplementationFlags(MethodImplAttributes.Runtime);
932
MethodWrapper mw = GetParameters()[0].GetMethods()[0];
934
invoke = (MethodInfo)mw.GetMethod();
937
internal override void EmitNewobj(CodeEmitter ilgen)
939
ilgen.Emit(OpCodes.Dup);
940
ilgen.Emit(OpCodes.Ldvirtftn, invoke);
941
ilgen.Emit(OpCodes.Newobj, constructor);
945
private static bool HasStructLayoutAttributeAnnotation(ClassFile c)
947
if (c.Annotations != null)
949
foreach (object[] annot in c.Annotations)
951
if ("Lcli/System/Runtime/InteropServices/StructLayoutAttribute$Annotation;".Equals(annot[1]))
961
private ClassFile.InnerClass getOuterClass()
963
ClassFile.InnerClass[] innerClasses = classFile.InnerClasses;
964
if (innerClasses != null)
966
for (int j = 0; j < innerClasses.Length; j++)
968
if (innerClasses[j].innerClass != 0
969
&& classFile.GetConstantPoolClass(innerClasses[j].innerClass) == classFile.Name)
971
return innerClasses[j];
975
return new ClassFile.InnerClass();
978
private bool IsSideEffectFreeStaticInitializerOrNoop(ClassFile.Method m, out bool noop)
980
if (m.ExceptionTable.Length != 0)
986
for (int i = 0; i < m.Instructions.Length; i++)
988
NormalizedByteCode bc = m.Instructions[i].NormalizedOpCode;
989
if (bc == NormalizedByteCode.__getstatic || bc == NormalizedByteCode.__putstatic)
991
ClassFile.ConstantPoolItemFieldref fld = classFile.SafeGetFieldref(m.Instructions[i].Arg1);
992
if (fld == null || fld.Class != classFile.Name)
997
// don't allow getstatic to load non-primitive fields, because that would
998
// cause the verifier to try to load the type
999
if (bc == NormalizedByteCode.__getstatic && "L[".IndexOf(fld.Signature[0]) != -1)
1004
if (bc == NormalizedByteCode.__putstatic)
1006
ClassFile.Field field = classFile.GetField(fld.Name, fld.Signature);
1012
if (!field.IsFinal || !field.IsStatic || !field.IsProperty || field.PropertySetter != null)
1018
else if (bc == NormalizedByteCode.__areturn ||
1019
bc == NormalizedByteCode.__ireturn ||
1020
bc == NormalizedByteCode.__lreturn ||
1021
bc == NormalizedByteCode.__freturn ||
1022
bc == NormalizedByteCode.__dreturn)
1027
else if (ByteCodeMetaData.CanThrowException(bc))
1032
else if (bc == NormalizedByteCode.__aconst_null
1033
|| bc == NormalizedByteCode.__return
1034
|| bc == NormalizedByteCode.__nop)
1036
// valid instructions in a potential noop <clinit>
1043
// the method needs to be verifiable to be side effect free, since we already analysed it,
1044
// we know that the verifier won't try to load any types (which isn't allowed at this time)
1047
new MethodAnalyzer(wrapper, null, classFile, m, wrapper.classLoader);
1055
#endif // STATIC_COMPILER
1057
private MethodWrapper GetMethodWrapperDuringCtor(TypeWrapper lookup, IList<MethodWrapper> methods, string name, string sig)
1059
if (lookup == wrapper)
1061
foreach (MethodWrapper mw in methods)
1063
if (mw.Name == name && mw.Signature == sig)
1068
if (lookup.BaseTypeWrapper == null)
1074
return lookup.BaseTypeWrapper.GetMethodWrapper(name, sig, true);
1079
return lookup.GetMethodWrapper(name, sig, true);
1083
private void AddMirandaMethods(List<MethodWrapper> methods, List<MethodWrapper[]> baseMethods, TypeWrapper tw)
1085
foreach (TypeWrapper iface in tw.Interfaces)
1087
if (iface.IsPublic && this.wrapper.IsInterface)
1089
// for interfaces, we only need miranda methods for non-public interfaces that we extend
1092
AddMirandaMethods(methods, baseMethods, iface);
1093
foreach (MethodWrapper ifmethod in iface.GetMethods())
1096
if (!ifmethod.IsStatic)
1098
TypeWrapper lookup = wrapper;
1099
while (lookup != null)
1101
MethodWrapper mw = GetMethodWrapperDuringCtor(lookup, methods, ifmethod.Name, ifmethod.Signature);
1104
mw = new TypicalMethodWrapper(wrapper, ifmethod.Name, ifmethod.Signature, null, null, null, Modifiers.Public | Modifiers.Abstract, MemberFlags.HideFromReflection | MemberFlags.MirandaMethod);
1106
baseMethods.Add(new MethodWrapper[] { ifmethod });
1109
if (!mw.IsStatic || mw.DeclaringType == wrapper)
1113
lookup = mw.DeclaringType.BaseTypeWrapper;
1120
private void AddDelegateInvokeStubs(TypeWrapper tw, ref MethodWrapper[] methods)
1122
foreach (TypeWrapper iface in tw.Interfaces)
1124
if (iface.IsFakeNestedType
1125
&& iface.GetMethods().Length == 1
1126
&& iface.GetMethods()[0].IsDelegateInvokeWithByRefParameter)
1128
MethodWrapper mw = new DelegateInvokeStubMethodWrapper(wrapper, iface.DeclaringTypeWrapper.TypeAsBaseType, iface.GetMethods()[0].Signature);
1129
if (GetMethodWrapperDuringCtor(wrapper, methods, mw.Name, mw.Signature) == null)
1131
Array.Resize(ref methods, methods.Length + 1);
1132
methods[methods.Length - 1] = mw;
1135
AddDelegateInvokeStubs(iface, ref methods);
1139
private sealed class DelegateInvokeStubMethodWrapper : MethodWrapper
1141
private readonly Type delegateType;
1143
internal DelegateInvokeStubMethodWrapper(TypeWrapper declaringType, Type delegateType, string sig)
1144
: base(declaringType, DotNetTypeWrapper.GetDelegateInvokeStubName(delegateType), sig, null, null, null, Modifiers.Public | Modifiers.Final, MemberFlags.HideFromReflection)
1146
this.delegateType = delegateType;
1149
internal MethodInfo DoLink(TypeBuilder tb)
1151
MethodWrapper mw = this.DeclaringType.GetMethodWrapper("Invoke", this.Signature, true);
1153
MethodInfo invoke = delegateType.GetMethod("Invoke");
1154
ParameterInfo[] parameters = invoke.GetParameters();
1155
Type[] parameterTypes = new Type[parameters.Length];
1156
for (int i = 0; i < parameterTypes.Length; i++)
1158
parameterTypes[i] = parameters[i].ParameterType;
1160
MethodBuilder mb = tb.DefineMethod(this.Name, MethodAttributes.Public, invoke.ReturnType, parameterTypes);
1161
AttributeHelper.HideFromReflection(mb);
1162
CodeEmitter ilgen = CodeEmitter.Create(mb);
1163
if (mw == null || mw.IsStatic || !mw.IsPublic)
1165
ilgen.EmitThrow(mw == null || mw.IsStatic ? "java.lang.AbstractMethodError" : "java.lang.IllegalAccessError", DeclaringType.Name + ".Invoke" + Signature);
1169
CodeEmitterLocal[] byrefs = new CodeEmitterLocal[parameters.Length];
1170
for (int i = 0; i < parameters.Length; i++)
1172
if (parameters[i].ParameterType.IsByRef)
1174
Type elemType = parameters[i].ParameterType.GetElementType();
1175
CodeEmitterLocal local = ilgen.DeclareLocal(ArrayTypeWrapper.MakeArrayType(elemType, 1));
1177
ilgen.Emit(OpCodes.Ldc_I4_1);
1178
ilgen.Emit(OpCodes.Newarr, elemType);
1179
ilgen.Emit(OpCodes.Stloc, local);
1180
ilgen.Emit(OpCodes.Ldloc, local);
1181
ilgen.Emit(OpCodes.Ldc_I4_0);
1182
ilgen.EmitLdarg(i + 1);
1183
ilgen.Emit(OpCodes.Ldobj, elemType);
1184
ilgen.Emit(OpCodes.Stelem, elemType);
1187
ilgen.BeginExceptionBlock();
1188
ilgen.Emit(OpCodes.Ldarg_0);
1189
for (int i = 0; i < parameters.Length; i++)
1191
if (byrefs[i] != null)
1193
ilgen.Emit(OpCodes.Ldloc, byrefs[i]);
1197
ilgen.EmitLdarg(i + 1);
1201
mw.EmitCallvirt(ilgen);
1202
CodeEmitterLocal returnValue = null;
1203
if (mw.ReturnType != PrimitiveTypeWrapper.VOID)
1205
returnValue = ilgen.DeclareLocal(mw.ReturnType.TypeAsSignatureType);
1206
ilgen.Emit(OpCodes.Stloc, returnValue);
1208
CodeEmitterLabel exit = ilgen.DefineLabel();
1209
ilgen.EmitLeave(exit);
1210
ilgen.BeginFinallyBlock();
1211
for (int i = 0; i < parameters.Length; i++)
1213
if (byrefs[i] != null)
1215
Type elemType = byrefs[i].LocalType.GetElementType();
1216
ilgen.EmitLdarg(i + 1);
1217
ilgen.Emit(OpCodes.Ldloc, byrefs[i]);
1218
ilgen.Emit(OpCodes.Ldc_I4_0);
1219
ilgen.Emit(OpCodes.Ldelem, elemType);
1220
ilgen.Emit(OpCodes.Stobj, elemType);
1223
ilgen.Emit(OpCodes.Endfinally);
1224
ilgen.EndExceptionBlock();
1225
ilgen.MarkLabel(exit);
1226
if (returnValue != null)
1228
ilgen.Emit(OpCodes.Ldloc, returnValue);
1230
ilgen.Emit(OpCodes.Ret);
1237
private static bool CheckInnerOuterNames(string inner, string outer)
1239
// do some sanity checks on the inner/outer class names
1240
return inner.Length > outer.Length + 1 && inner[outer.Length] == '$' && inner.StartsWith(outer);
1243
private string GetInnerClassName(string outer, string inner)
1245
Debug.Assert(CheckInnerOuterNames(inner, outer));
1246
if (nestedTypeNames == null)
1248
nestedTypeNames = new Dictionary<string, TypeWrapper>();
1250
return DynamicClassLoader.TypeNameMangleImpl(nestedTypeNames, inner.Substring(outer.Length + 1), null);
1252
#endif // STATIC_COMPILER
1254
private int GetMethodIndex(MethodWrapper mw)
1256
for (int i = 0; i < methods.Length; i++)
1258
if (methods[i] == mw)
1263
throw new InvalidOperationException();
1266
private static void CheckLoaderConstraints(MethodWrapper mw, MethodWrapper baseMethod)
1268
#if !STATIC_COMPILER
1269
if (JVM.FinishingForDebugSave)
1271
// when we're finishing types to save a debug image (in dynamic mode) we don't care about loader constraints anymore
1272
// (and we can't throw a LinkageError, because that would prevent the debug image from being saved)
1276
if (mw.ReturnType != baseMethod.ReturnType)
1278
if (mw.ReturnType.IsUnloadable || baseMethod.ReturnType.IsUnloadable)
1280
// unloadable types can never cause a loader constraint violation
1281
if (mw.ReturnType.IsUnloadable && baseMethod.ReturnType.IsUnloadable)
1283
((UnloadableTypeWrapper)mw.ReturnType).SetCustomModifier(((UnloadableTypeWrapper)baseMethod.ReturnType).CustomModifier);
1289
StaticCompiler.LinkageError("Method \"{2}.{3}{4}\" has a return type \"{0}\" and tries to override method \"{5}.{3}{4}\" that has a return type \"{1}\"", mw.ReturnType, baseMethod.ReturnType, mw.DeclaringType.Name, mw.Name, mw.Signature, baseMethod.DeclaringType.Name);
1291
throw new LinkageError("Loader constraints violated");
1294
TypeWrapper[] here = mw.GetParameters();
1295
TypeWrapper[] there = baseMethod.GetParameters();
1296
for (int i = 0; i < here.Length; i++)
1298
if (here[i] != there[i])
1300
if (here[i].IsUnloadable || there[i].IsUnloadable)
1302
// unloadable types can never cause a loader constraint violation
1303
if (here[i].IsUnloadable && there[i].IsUnloadable)
1305
((UnloadableTypeWrapper)here[i]).SetCustomModifier(((UnloadableTypeWrapper)there[i]).CustomModifier);
1311
StaticCompiler.LinkageError("Method \"{2}.{3}{4}\" has an argument type \"{0}\" and tries to override method \"{5}.{3}{4}\" that has an argument type \"{1}\"", here[i], there[i], mw.DeclaringType.Name, mw.Name, mw.Signature, baseMethod.DeclaringType.Name);
1313
throw new LinkageError("Loader constraints violated");
1319
private int GetFieldIndex(FieldWrapper fw)
1321
for (int i = 0; i < fields.Length; i++)
1323
if (fields[i] == fw)
1328
throw new InvalidOperationException();
1331
internal override FieldInfo LinkField(FieldWrapper fw)
1333
if (fw is DynamicPropertyFieldWrapper)
1335
((DynamicPropertyFieldWrapper)fw).DoLink(typeBuilder);
1338
int fieldIndex = GetFieldIndex(fw);
1340
// for compatibility with broken Java code that assumes that reflection returns the fields in class declaration
1341
// order, we emit the fields in class declaration order in the .NET metadata (and then when we retrieve them
1342
// using .NET reflection, we sort on metadata token.)
1345
if (!fields[fieldIndex - 1].IsLinked)
1347
for (int i = 0; i < fieldIndex; i++)
1353
if (fieldIndex >= classFile.Fields.Length)
1355
// this must be a field defined in map.xml
1356
FieldAttributes fieldAttribs = 0;
1359
fieldAttribs |= FieldAttributes.Public;
1361
else if (fw.IsProtected)
1363
fieldAttribs |= FieldAttributes.FamORAssem;
1365
else if (fw.IsPrivate)
1367
fieldAttribs |= FieldAttributes.Private;
1371
fieldAttribs |= FieldAttributes.Assembly;
1375
fieldAttribs |= FieldAttributes.Static;
1379
fieldAttribs |= FieldAttributes.InitOnly;
1381
return DefineField(fw.Name, fw.FieldTypeWrapper, fieldAttribs, fw.IsVolatile);
1383
#endif // STATIC_COMPILER
1385
ClassFile.Field fld = classFile.Fields[fieldIndex];
1386
string realFieldName = fld.Name;
1387
FieldAttributes attribs = 0;
1388
MethodAttributes methodAttribs = MethodAttributes.HideBySig;
1390
bool setModifiers = fld.IsInternal || (fld.Modifiers & (Modifiers.Synthetic | Modifiers.Enum)) != 0;
1394
attribs |= FieldAttributes.Private;
1396
else if (fld.IsProtected)
1398
attribs |= FieldAttributes.FamORAssem;
1399
methodAttribs |= MethodAttributes.FamORAssem;
1401
else if (fld.IsPublic)
1403
attribs |= FieldAttributes.Public;
1404
methodAttribs |= MethodAttributes.Public;
1408
attribs |= FieldAttributes.Assembly;
1409
methodAttribs |= MethodAttributes.Assembly;
1414
attribs |= FieldAttributes.Static;
1415
methodAttribs |= MethodAttributes.Static;
1417
// NOTE "constant" static finals are converted into literals
1418
// TODO it would be possible for Java code to change the value of a non-blank static final, but I don't
1419
// know if we want to support this (since the Java JITs don't really support it either)
1420
if (fld.IsStaticFinalConstant)
1422
Profiler.Count("Static Final Constant");
1423
attribs |= FieldAttributes.Literal;
1424
field = DefineField(fld.Name, fw.FieldTypeWrapper, attribs, false);
1425
field.SetConstant(fld.ConstantValue);
1430
if (wrapper.IsPublic && wrapper.NeedsType2AccessStub(fw))
1432
// this field is going to get a type 2 access stub, so we hide the actual field
1433
attribs &= ~FieldAttributes.FieldAccessMask;
1434
attribs |= FieldAttributes.Assembly;
1435
// instead of adding HideFromJava we rename the field to avoid confusing broken compilers
1436
// see https://sourceforge.net/tracker/?func=detail&atid=525264&aid=3056721&group_id=69637
1437
// additional note: now that we maintain the ordering of the fields, we need to recognize
1438
// these fields so that we know where to insert the corresponding accessor property FieldWrapper.
1439
realFieldName = NamePrefix.Type2AccessStubBackingField + fld.Name;
1441
else if (fld.IsFinal)
1443
if (wrapper.IsInterface || wrapper.classLoader.StrictFinalFieldSemantics)
1445
attribs |= FieldAttributes.InitOnly;
1449
setModifiers = true;
1453
if (fld.IsFinal && wrapper.IsInterface)
1455
attribs |= FieldAttributes.InitOnly;
1459
field = DefineField(realFieldName, fw.FieldTypeWrapper, attribs, fld.IsVolatile);
1461
if (fld.IsTransient)
1463
CustomAttributeBuilder transientAttrib = new CustomAttributeBuilder(JVM.Import(typeof(NonSerializedAttribute)).GetConstructor(Type.EmptyTypes), new object[0]);
1464
field.SetCustomAttribute(transientAttrib);
1468
// if the Java modifiers cannot be expressed in .NET, we emit the Modifiers attribute to store
1469
// the Java modifiers
1472
AttributeHelper.SetModifiers(field, fld.Modifiers, fld.IsInternal);
1474
if (fld.DeprecatedAttribute)
1476
AttributeHelper.SetDeprecatedAttribute(field);
1478
if (fld.GenericSignature != null)
1480
AttributeHelper.SetSignatureAttribute(field, fld.GenericSignature);
1483
#endif // STATIC_COMPILER
1487
private FieldBuilder DefineField(string name, TypeWrapper tw, FieldAttributes attribs, bool isVolatile)
1489
Type[] modreq = isVolatile ? new Type[] { Types.IsVolatile } : Type.EmptyTypes;
1490
return typeBuilder.DefineField(name, tw.TypeAsSignatureType, modreq, wrapper.GetModOpt(tw, false), attribs);
1493
internal override void EmitRunClassConstructor(CodeEmitter ilgen)
1495
if (clinitMethod != null)
1497
ilgen.Emit(OpCodes.Call, clinitMethod);
1501
internal override DynamicImpl Finish()
1503
if (wrapper.BaseTypeWrapper != null)
1505
wrapper.BaseTypeWrapper.Finish();
1507
// NOTE there is a bug in the CLR (.NET 1.0 & 1.1 [1.2 is not yet available]) that
1508
// causes the AppDomain.TypeResolve event to receive the incorrect type name for nested types.
1509
// The Name in the ResolveEventArgs contains only the nested type name, not the full type name,
1510
// for example, if the type being resolved is "MyOuterType+MyInnerType", then the event only
1511
// receives "MyInnerType" as the name. Since we only compile inner classes as nested types
1512
// when we're statically compiling, we can only run into this bug when we're statically compiling.
1513
// NOTE To work around this bug, we have to make sure that all types that are going to be
1514
// required in finished form, are finished explicitly here. It isn't clear what other types are
1515
// required to be finished. I instrumented a static compilation of classpath.dll and this
1516
// turned up no other cases of the TypeResolve event firing.
1517
for (int i = 0; i < wrapper.Interfaces.Length; i++)
1519
wrapper.Interfaces[i].Finish();
1521
// make sure all classes are loaded, before we start finishing the type. During finishing, we
1522
// may not run any Java code, because that might result in a request to finish the type that we
1523
// are in the process of finishing, and this would be a problem.
1524
classFile.Link(wrapper);
1525
for (int i = 0; i < fields.Length; i++)
1529
for (int i = 0; i < methods.Length; i++)
1533
// this is the correct lock, FinishCore doesn't call any user code and mutates global state,
1534
// so it needs to be protected by a lock.
1537
FinishedTypeImpl impl;
1540
// call FinishCore in the finally to avoid Thread.Abort interrupting the thread
1544
impl = FinishCore();
1550
private FinishedTypeImpl FinishCore()
1552
// it is possible that the loading of the referenced classes triggered a finish of us,
1553
// if that happens, we just return
1554
if (finishedType != null)
1556
return finishedType;
1558
if (finishInProgress)
1560
throw new InvalidOperationException("Recursive finish attempt for " + wrapper.Name);
1562
finishInProgress = true;
1563
Tracer.Info(Tracer.Compiler, "Finishing: {0}", wrapper.Name);
1564
Profiler.Enter("JavaTypeImpl.Finish.Core");
1567
TypeWrapper declaringTypeWrapper = null;
1568
TypeWrapper[] innerClassesTypeWrappers = TypeWrapper.EmptyArray;
1569
// if we're an inner class, we need to attach an InnerClass attribute
1570
ClassFile.InnerClass[] innerclasses = classFile.InnerClasses;
1571
if (innerclasses != null)
1573
// TODO consider not pre-computing innerClassesTypeWrappers and declaringTypeWrapper here
1574
List<TypeWrapper> wrappers = new List<TypeWrapper>();
1575
for (int i = 0; i < innerclasses.Length; i++)
1577
if (innerclasses[i].innerClass != 0 && innerclasses[i].outerClass != 0)
1579
if (classFile.GetConstantPoolClassType(innerclasses[i].outerClass) == wrapper)
1581
wrappers.Add(classFile.GetConstantPoolClassType(innerclasses[i].innerClass));
1583
if (classFile.GetConstantPoolClassType(innerclasses[i].innerClass) == wrapper)
1585
declaringTypeWrapper = classFile.GetConstantPoolClassType(innerclasses[i].outerClass);
1589
innerClassesTypeWrappers = wrappers.ToArray();
1591
// before we bake our type, we need to link any inner annotations to allow them to create their attribute type (as a nested type)
1592
foreach (TypeWrapper tw in innerClassesTypeWrappers)
1594
DynamicTypeWrapper dtw = tw as DynamicTypeWrapper;
1597
JavaTypeImpl impl = dtw.impl as JavaTypeImpl;
1600
if (impl.annotationBuilder != null)
1602
impl.annotationBuilder.Link();
1607
#endif //STATIC_COMPILER
1610
if (annotationBuilder != null)
1612
CustomAttributeBuilder cab = new CustomAttributeBuilder(JVM.LoadType(typeof(AnnotationAttributeAttribute)).GetConstructor(new Type[] { Types.String }), new object[] { annotationBuilder.AttributeTypeName });
1613
typeBuilder.SetCustomAttribute(cab);
1615
if (!wrapper.IsInterface && wrapper.IsMapUnsafeException)
1617
// mark all exceptions that are unsafe for mapping with a custom attribute,
1618
// so that at runtime we can quickly assertain if an exception type can be
1619
// caught without filtering
1620
AttributeHelper.SetExceptionIsUnsafeForMapping(typeBuilder);
1624
FinishContext context = new FinishContext(classFile, wrapper, typeBuilder);
1625
Type type = context.FinishImpl();
1627
if (annotationBuilder != null)
1629
annotationBuilder.Finish(this);
1631
if (enumBuilder != null)
1633
enumBuilder.CreateType();
1636
MethodInfo finishedClinitMethod = clinitMethod;
1637
#if !STATIC_COMPILER
1638
if (finishedClinitMethod != null)
1640
// In dynamic mode, we may need to emit a call to this method from a DynamicMethod which doesn't support calling unfinished methods,
1641
// so we must resolve to the real method here.
1642
finishedClinitMethod = type.GetMethod("__<clinit>", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
1645
finishedType = new FinishedTypeImpl(type, innerClassesTypeWrappers, declaringTypeWrapper, wrapper.ReflectiveModifiers, Metadata.Create(classFile), finishedClinitMethod, finalizeMethod);
1646
return finishedType;
1648
#if !STATIC_COMPILER
1651
JVM.CriticalFailure("Exception during finishing of: " + wrapper.Name, x);
1657
Profiler.Leave("JavaTypeImpl.Finish.Core");
1662
private bool IsValidAnnotationElementType(string type)
1666
type = type.Substring(1);
1678
case "Ljava.lang.String;":
1679
case "Ljava.lang.Class;":
1682
if (type.StartsWith("L") && type.EndsWith(";"))
1686
TypeWrapper tw = wrapper.GetClassLoader().LoadClassByDottedNameFast(type.Substring(1, type.Length - 2));
1689
if ((tw.Modifiers & Modifiers.Annotation) != 0)
1693
if ((tw.Modifiers & Modifiers.Enum) != 0)
1695
TypeWrapper enumType = ClassLoaderWrapper.GetBootstrapClassLoader().LoadClassByDottedNameFast("java.lang.Enum");
1696
if (enumType != null && tw.IsSubTypeOf(enumType))
1710
sealed class AnnotationBuilder : Annotation
1712
private JavaTypeImpl impl;
1713
private TypeBuilder outer;
1714
private TypeBuilder annotationTypeBuilder;
1715
private TypeBuilder attributeTypeBuilder;
1716
private MethodBuilder defineConstructor;
1718
internal AnnotationBuilder(JavaTypeImpl o, TypeBuilder outer)
1724
internal void Link()
1730
JavaTypeImpl o = impl;
1733
// Make sure the annotation type only has valid methods
1734
for (int i = 0; i < o.methods.Length; i++)
1736
if (!o.methods[i].IsStatic)
1738
if (!o.methods[i].Signature.StartsWith("()"))
1742
if (!o.IsValidAnnotationElementType(o.methods[i].Signature.Substring(2)))
1749
// we only set annotationTypeBuilder if we're valid
1750
annotationTypeBuilder = o.typeBuilder;
1752
TypeWrapper annotationAttributeBaseType = ClassLoaderWrapper.LoadClassCritical("ikvm.internal.AnnotationAttributeBase");
1754
// make sure we don't clash with another class name
1755
CompilerClassLoader ccl = o.wrapper.classLoader;
1756
string name = o.classFile.Name;
1757
while (!ccl.ReserveName(name + "Attribute"))
1762
TypeAttributes typeAttributes = TypeAttributes.Class | TypeAttributes.Sealed;
1763
if (o.outerClassWrapper != null)
1765
if (o.wrapper.IsPublic)
1767
typeAttributes |= TypeAttributes.NestedPublic;
1771
typeAttributes |= TypeAttributes.NestedAssembly;
1773
attributeTypeBuilder = outer.DefineNestedType(o.GetInnerClassName(o.outerClassWrapper.Name, name + "Attribute"), typeAttributes, annotationAttributeBaseType.TypeAsBaseType);
1777
if (o.wrapper.IsPublic)
1779
typeAttributes |= TypeAttributes.Public;
1783
typeAttributes |= TypeAttributes.NotPublic;
1785
attributeTypeBuilder = o.wrapper.classLoader.GetTypeWrapperFactory().ModuleBuilder.DefineType(name + "Attribute", typeAttributes, annotationAttributeBaseType.TypeAsBaseType);
1787
if (o.wrapper.IsPublic)
1789
// In the Java world, the class appears as a non-public proxy class
1790
AttributeHelper.SetModifiers(attributeTypeBuilder, Modifiers.Final, false);
1792
// NOTE we "abuse" the InnerClassAttribute to add a custom attribute to name the class "$Proxy[Annotation]" in the Java world
1793
int dotindex = o.classFile.Name.LastIndexOf('.') + 1;
1794
AttributeHelper.SetInnerClass(attributeTypeBuilder, o.classFile.Name.Substring(0, dotindex) + "$Proxy" + o.classFile.Name.Substring(dotindex), Modifiers.Final);
1795
attributeTypeBuilder.AddInterfaceImplementation(o.typeBuilder);
1796
AttributeHelper.SetImplementsAttribute(attributeTypeBuilder, new TypeWrapper[] { o.wrapper });
1798
if (o.classFile.Annotations != null)
1800
CustomAttributeBuilder attributeUsageAttribute = null;
1801
bool hasAttributeUsageAttribute = false;
1802
foreach (object[] def in o.classFile.Annotations)
1804
if (def[1].Equals("Ljava/lang/annotation/Target;") && !hasAttributeUsageAttribute)
1806
for (int i = 2; i < def.Length; i += 2)
1808
if (def[i].Equals("value"))
1810
object[] val = def[i + 1] as object[];
1813
&& val[0].Equals(AnnotationDefaultAttribute.TAG_ARRAY))
1815
AttributeTargets targets = 0;
1816
for (int j = 1; j < val.Length; j++)
1818
object[] eval = val[j] as object[];
1821
&& eval[0].Equals(AnnotationDefaultAttribute.TAG_ENUM)
1822
&& eval[1].Equals("Ljava/lang/annotation/ElementType;"))
1824
switch ((string)eval[2])
1826
case "ANNOTATION_TYPE":
1827
targets |= AttributeTargets.Interface;
1830
targets |= AttributeTargets.Constructor;
1833
targets |= AttributeTargets.Field;
1835
case "LOCAL_VARIABLE":
1838
targets |= AttributeTargets.Method;
1841
targets |= AttributeTargets.Interface;
1844
targets |= AttributeTargets.Parameter;
1847
targets |= AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Struct | AttributeTargets.Delegate | AttributeTargets.Enum;
1852
attributeUsageAttribute = new CustomAttributeBuilder(JVM.Import(typeof(AttributeUsageAttribute)).GetConstructor(new Type[] { JVM.Import(typeof(AttributeTargets)) }), new object[] { targets });
1859
// apply any .NET custom attributes that are on the annotation to the custom attribute we synthesize
1860
// (for example, to allow AttributeUsageAttribute to be overridden)
1861
Annotation annotation = Annotation.Load(o.wrapper.GetClassLoader(), def);
1862
if (annotation != null && annotation.IsCustomAttribute)
1864
annotation.Apply(o.wrapper.GetClassLoader(), attributeTypeBuilder, def);
1866
if (def[1].Equals("Lcli/System/AttributeUsageAttribute$Annotation;"))
1868
hasAttributeUsageAttribute = true;
1872
if (attributeUsageAttribute != null && !hasAttributeUsageAttribute)
1874
attributeTypeBuilder.SetCustomAttribute(attributeUsageAttribute);
1878
defineConstructor = ReflectUtil.DefineConstructor(attributeTypeBuilder, MethodAttributes.Public, new Type[] { JVM.Import(typeof(object[])) });
1879
AttributeHelper.SetEditorBrowsableNever(defineConstructor);
1882
private static Type TypeWrapperToAnnotationParameterType(TypeWrapper tw)
1884
bool isArray = false;
1888
tw = tw.ElementTypeWrapper;
1890
if (tw.Annotation != null)
1892
// we don't support Annotation args
1898
if (tw == CoreClasses.java.lang.Class.Wrapper)
1900
argType = Types.Type;
1902
else if (tw.EnumType != null)
1904
argType = tw.EnumType;
1908
argType = tw.TypeAsSignatureType;
1912
argType = ArrayTypeWrapper.MakeArrayType(argType, 1);
1918
internal string AttributeTypeName
1923
if (attributeTypeBuilder != null)
1925
return attributeTypeBuilder.FullName;
1931
private static void EmitSetValueCall(TypeWrapper annotationAttributeBaseType, CodeEmitter ilgen, string name, TypeWrapper tw, int argIndex)
1933
ilgen.Emit(OpCodes.Ldarg_0);
1934
ilgen.Emit(OpCodes.Ldstr, name);
1935
ilgen.EmitLdarg(argIndex);
1936
if (tw.TypeAsSignatureType.IsValueType)
1938
ilgen.Emit(OpCodes.Box, tw.TypeAsSignatureType);
1940
else if (tw.EnumType != null)
1942
ilgen.Emit(OpCodes.Box, tw.EnumType);
1944
MethodWrapper setValueMethod = annotationAttributeBaseType.GetMethodWrapper("setValue", "(Ljava.lang.String;Ljava.lang.Object;)V", false);
1945
setValueMethod.Link();
1946
setValueMethod.EmitCall(ilgen);
1949
internal void Finish(JavaTypeImpl o)
1952
if (annotationTypeBuilder == null)
1954
// not a valid annotation type
1957
TypeWrapper annotationAttributeBaseType = ClassLoaderWrapper.LoadClassCritical("ikvm.internal.AnnotationAttributeBase");
1958
annotationAttributeBaseType.Finish();
1960
int requiredArgCount = 0;
1962
bool unsupported = false;
1963
for (int i = 0; i < o.methods.Length; i++)
1965
if (!o.methods[i].IsStatic)
1967
if (valueArg == -1 && o.methods[i].Name == "value")
1971
if (o.classFile.Methods[i].AnnotationDefault == null)
1973
if (TypeWrapperToAnnotationParameterType(o.methods[i].ReturnType) == null)
1983
MethodBuilder defaultConstructor = ReflectUtil.DefineConstructor(attributeTypeBuilder, unsupported || requiredArgCount > 0 ? MethodAttributes.Private : MethodAttributes.Public, Type.EmptyTypes);
1988
if (requiredArgCount > 0)
1990
Type[] args = new Type[requiredArgCount];
1991
for (int i = 0, j = 0; i < o.methods.Length; i++)
1993
if (!o.methods[i].IsStatic)
1995
if (o.classFile.Methods[i].AnnotationDefault == null)
1997
args[j++] = TypeWrapperToAnnotationParameterType(o.methods[i].ReturnType);
2001
MethodBuilder reqArgConstructor = ReflectUtil.DefineConstructor(attributeTypeBuilder, MethodAttributes.Public, args);
2002
AttributeHelper.HideFromJava(reqArgConstructor);
2003
ilgen = CodeEmitter.Create(reqArgConstructor);
2004
ilgen.Emit(OpCodes.Ldarg_0);
2005
ilgen.Emit(OpCodes.Call, defaultConstructor);
2006
for (int i = 0, j = 0; i < o.methods.Length; i++)
2008
if (!o.methods[i].IsStatic)
2010
if (o.classFile.Methods[i].AnnotationDefault == null)
2012
reqArgConstructor.DefineParameter(++j, ParameterAttributes.None, o.methods[i].Name);
2013
EmitSetValueCall(annotationAttributeBaseType, ilgen, o.methods[i].Name, o.methods[i].ReturnType, j);
2017
ilgen.Emit(OpCodes.Ret);
2020
else if (valueArg != -1)
2022
// We don't have any required parameters, but we do have an optional "value" parameter,
2023
// so we create an additional constructor (the default constructor will be public in this case)
2024
// that accepts the value parameter.
2025
Type argType = TypeWrapperToAnnotationParameterType(o.methods[valueArg].ReturnType);
2026
if (argType != null)
2028
MethodBuilder cb = ReflectUtil.DefineConstructor(attributeTypeBuilder, MethodAttributes.Public, new Type[] { argType });
2029
AttributeHelper.HideFromJava(cb);
2030
cb.DefineParameter(1, ParameterAttributes.None, "value");
2031
ilgen = CodeEmitter.Create(cb);
2032
ilgen.Emit(OpCodes.Ldarg_0);
2033
ilgen.Emit(OpCodes.Call, defaultConstructor);
2034
EmitSetValueCall(annotationAttributeBaseType, ilgen, "value", o.methods[valueArg].ReturnType, 1);
2035
ilgen.Emit(OpCodes.Ret);
2041
ilgen = CodeEmitter.Create(defaultConstructor);
2042
ilgen.Emit(OpCodes.Ldarg_0);
2043
o.wrapper.EmitClassLiteral(ilgen);
2044
annotationAttributeBaseType.GetMethodWrapper("<init>", "(Ljava.lang.Class;)V", false).EmitCall(ilgen);
2045
ilgen.Emit(OpCodes.Ret);
2048
ilgen = CodeEmitter.Create(defineConstructor);
2049
ilgen.Emit(OpCodes.Ldarg_0);
2050
ilgen.Emit(OpCodes.Call, defaultConstructor);
2051
ilgen.Emit(OpCodes.Ldarg_0);
2052
ilgen.Emit(OpCodes.Ldarg_1);
2053
annotationAttributeBaseType.GetMethodWrapper("setDefinition", "([Ljava.lang.Object;)V", false).EmitCall(ilgen);
2054
ilgen.Emit(OpCodes.Ret);
2057
MethodWrapper getValueMethod = annotationAttributeBaseType.GetMethodWrapper("getValue", "(Ljava.lang.String;)Ljava.lang.Object;", false);
2058
MethodWrapper getByteValueMethod = annotationAttributeBaseType.GetMethodWrapper("getByteValue", "(Ljava.lang.String;)B", false);
2059
MethodWrapper getBooleanValueMethod = annotationAttributeBaseType.GetMethodWrapper("getBooleanValue", "(Ljava.lang.String;)Z", false);
2060
MethodWrapper getCharValueMethod = annotationAttributeBaseType.GetMethodWrapper("getCharValue", "(Ljava.lang.String;)C", false);
2061
MethodWrapper getShortValueMethod = annotationAttributeBaseType.GetMethodWrapper("getShortValue", "(Ljava.lang.String;)S", false);
2062
MethodWrapper getIntValueMethod = annotationAttributeBaseType.GetMethodWrapper("getIntValue", "(Ljava.lang.String;)I", false);
2063
MethodWrapper getFloatValueMethod = annotationAttributeBaseType.GetMethodWrapper("getFloatValue", "(Ljava.lang.String;)F", false);
2064
MethodWrapper getLongValueMethod = annotationAttributeBaseType.GetMethodWrapper("getLongValue", "(Ljava.lang.String;)J", false);
2065
MethodWrapper getDoubleValueMethod = annotationAttributeBaseType.GetMethodWrapper("getDoubleValue", "(Ljava.lang.String;)D", false);
2066
for (int i = 0; i < o.methods.Length; i++)
2069
if (!o.methods[i].IsStatic)
2071
MethodBuilder mb = o.methods[i].GetDefineMethodHelper().DefineMethod(o.wrapper, attributeTypeBuilder, o.methods[i].Name, MethodAttributes.Private | MethodAttributes.Virtual | MethodAttributes.Final | MethodAttributes.NewSlot);
2072
attributeTypeBuilder.DefineMethodOverride(mb, (MethodInfo)o.methods[i].GetMethod());
2073
ilgen = CodeEmitter.Create(mb);
2074
ilgen.Emit(OpCodes.Ldarg_0);
2075
ilgen.Emit(OpCodes.Ldstr, o.methods[i].Name);
2076
if (o.methods[i].ReturnType.IsPrimitive)
2078
if (o.methods[i].ReturnType == PrimitiveTypeWrapper.BYTE)
2080
getByteValueMethod.EmitCall(ilgen);
2082
else if (o.methods[i].ReturnType == PrimitiveTypeWrapper.BOOLEAN)
2084
getBooleanValueMethod.EmitCall(ilgen);
2086
else if (o.methods[i].ReturnType == PrimitiveTypeWrapper.CHAR)
2088
getCharValueMethod.EmitCall(ilgen);
2090
else if (o.methods[i].ReturnType == PrimitiveTypeWrapper.SHORT)
2092
getShortValueMethod.EmitCall(ilgen);
2094
else if (o.methods[i].ReturnType == PrimitiveTypeWrapper.INT)
2096
getIntValueMethod.EmitCall(ilgen);
2098
else if (o.methods[i].ReturnType == PrimitiveTypeWrapper.FLOAT)
2100
getFloatValueMethod.EmitCall(ilgen);
2102
else if (o.methods[i].ReturnType == PrimitiveTypeWrapper.LONG)
2104
getLongValueMethod.EmitCall(ilgen);
2106
else if (o.methods[i].ReturnType == PrimitiveTypeWrapper.DOUBLE)
2108
getDoubleValueMethod.EmitCall(ilgen);
2112
throw new InvalidOperationException();
2117
getValueMethod.EmitCall(ilgen);
2118
o.methods[i].ReturnType.EmitCheckcast(null, ilgen);
2120
ilgen.Emit(OpCodes.Ret);
2123
if (o.classFile.Methods[i].AnnotationDefault != null
2124
&& !(o.methods[i].Name == "value" && requiredArgCount == 0))
2126
// now add a .NET property for this annotation optional parameter
2127
Type argType = TypeWrapperToAnnotationParameterType(o.methods[i].ReturnType);
2128
if (argType != null)
2130
PropertyBuilder pb = attributeTypeBuilder.DefineProperty(o.methods[i].Name, PropertyAttributes.None, argType, Type.EmptyTypes);
2131
AttributeHelper.HideFromJava(pb);
2132
MethodBuilder setter = attributeTypeBuilder.DefineMethod("set_" + o.methods[i].Name, MethodAttributes.Public, Types.Void, new Type[] { argType });
2133
AttributeHelper.HideFromJava(setter);
2134
pb.SetSetMethod(setter);
2135
ilgen = CodeEmitter.Create(setter);
2136
EmitSetValueCall(annotationAttributeBaseType, ilgen, o.methods[i].Name, o.methods[i].ReturnType, 1);
2137
ilgen.Emit(OpCodes.Ret);
2139
MethodBuilder getter = attributeTypeBuilder.DefineMethod("get_" + o.methods[i].Name, MethodAttributes.Public, argType, Type.EmptyTypes);
2140
AttributeHelper.HideFromJava(getter);
2141
pb.SetGetMethod(getter);
2142
// TODO implement the getter method
2143
ilgen = CodeEmitter.Create(getter);
2144
ilgen.ThrowException(JVM.Import(typeof(NotImplementedException)));
2150
attributeTypeBuilder.CreateType();
2153
internal override void Apply(ClassLoaderWrapper loader, TypeBuilder tb, object annotation)
2156
if (annotationTypeBuilder != null)
2158
annotation = QualifyClassNames(loader, annotation);
2159
tb.SetCustomAttribute(new CustomAttributeBuilder(defineConstructor.__AsConstructorInfo(), new object[] { annotation }));
2163
internal override void Apply(ClassLoaderWrapper loader, MethodBuilder mb, object annotation)
2166
if (annotationTypeBuilder != null)
2168
annotation = QualifyClassNames(loader, annotation);
2169
mb.SetCustomAttribute(new CustomAttributeBuilder(defineConstructor.__AsConstructorInfo(), new object[] { annotation }));
2173
internal override void Apply(ClassLoaderWrapper loader, FieldBuilder fb, object annotation)
2176
if (annotationTypeBuilder != null)
2178
annotation = QualifyClassNames(loader, annotation);
2179
fb.SetCustomAttribute(new CustomAttributeBuilder(defineConstructor.__AsConstructorInfo(), new object[] { annotation }));
2183
internal override void Apply(ClassLoaderWrapper loader, ParameterBuilder pb, object annotation)
2186
if (annotationTypeBuilder != null)
2188
annotation = QualifyClassNames(loader, annotation);
2189
pb.SetCustomAttribute(new CustomAttributeBuilder(defineConstructor.__AsConstructorInfo(), new object[] { annotation }));
2193
internal override void Apply(ClassLoaderWrapper loader, AssemblyBuilder ab, object annotation)
2196
if (annotationTypeBuilder != null)
2198
annotation = QualifyClassNames(loader, annotation);
2199
ab.SetCustomAttribute(new CustomAttributeBuilder(defineConstructor.__AsConstructorInfo(), new object[] { annotation }));
2203
internal override void Apply(ClassLoaderWrapper loader, PropertyBuilder pb, object annotation)
2206
if (annotationTypeBuilder != null)
2208
annotation = QualifyClassNames(loader, annotation);
2209
pb.SetCustomAttribute(new CustomAttributeBuilder(defineConstructor.__AsConstructorInfo(), new object[] { annotation }));
2213
internal override bool IsCustomAttribute
2215
get { return false; }
2218
#endif // STATIC_COMPILER
2220
internal override TypeWrapper[] InnerClasses
2224
throw new InvalidOperationException("InnerClasses is only available for finished types");
2228
internal override TypeWrapper DeclaringTypeWrapper
2232
throw new InvalidOperationException("DeclaringTypeWrapper is only available for finished types");
2236
internal override Modifiers ReflectiveModifiers
2241
ClassFile.InnerClass[] innerclasses = classFile.InnerClasses;
2242
if (innerclasses != null)
2244
for (int i = 0; i < innerclasses.Length; i++)
2246
if (innerclasses[i].innerClass != 0)
2248
if (classFile.GetConstantPoolClass(innerclasses[i].innerClass) == wrapper.Name)
2250
// the mask comes from RECOGNIZED_INNER_CLASS_MODIFIERS in src/hotspot/share/vm/classfile/classFileParser.cpp
2251
// (minus ACC_SUPER)
2252
mods = innerclasses[i].accessFlags & (Modifiers)0x761F;
2253
if (classFile.IsInterface)
2255
mods |= Modifiers.Abstract;
2262
// the mask comes from JVM_RECOGNIZED_CLASS_MODIFIERS in src/hotspot/share/vm/prims/jvm.h
2263
// (minus ACC_SUPER)
2264
mods = classFile.Modifiers & (Modifiers)0x7611;
2265
if (classFile.IsInterface)
2267
mods |= Modifiers.Abstract;
2273
// this finds all methods that the specified name/sig is going to be overriding
2274
private MethodWrapper[] FindBaseMethods(ClassFile.Method m, out bool explicitOverride)
2276
Debug.Assert(!classFile.IsInterface);
2277
Debug.Assert(m.Name != "<init>");
2279
// starting with Java 7 the algorithm changed
2280
return classFile.MajorVersion >= 51
2281
? FindBaseMethods7(m.Name, m.Signature, m.IsFinal && !m.IsPublic && !m.IsProtected, out explicitOverride)
2282
: FindBaseMethodsLegacy(m.Name, m.Signature, out explicitOverride);
2285
private MethodWrapper[] FindBaseMethods7(string name, string sig, bool packageFinal, out bool explicitOverride)
2287
// NOTE this implements the (completely broken) OpenJDK 7 b147 HotSpot behavior,
2288
// not the algorithm specified in section 5.4.5 of the JavaSE7 JVM spec
2289
// see http://weblog.ikvm.net/PermaLink.aspx?guid=bde44d8b-7ba9-4e0e-b3a6-b735627118ff and subsequent posts
2290
explicitOverride = false;
2291
MethodWrapper topPublicOrProtectedMethod = null;
2292
TypeWrapper tw = wrapper.BaseTypeWrapper;
2295
MethodWrapper baseMethod = tw.GetMethodWrapper(name, sig, true);
2296
if (baseMethod == null)
2300
else if (baseMethod.IsAccessStub)
2304
else if (!baseMethod.IsStatic && (baseMethod.IsPublic || baseMethod.IsProtected))
2306
topPublicOrProtectedMethod = baseMethod;
2308
tw = baseMethod.DeclaringType.BaseTypeWrapper;
2310
tw = wrapper.BaseTypeWrapper;
2313
MethodWrapper baseMethod = tw.GetMethodWrapper(name, sig, true);
2314
if (baseMethod == null)
2318
else if (baseMethod.IsAccessStub)
2322
else if (baseMethod.IsPrivate)
2326
else if (baseMethod.IsFinal && (baseMethod.IsPublic || baseMethod.IsProtected || baseMethod.DeclaringType.IsPackageAccessibleFrom(wrapper)))
2328
throw new VerifyError("final method " + baseMethod.Name + baseMethod.Signature + " in " + baseMethod.DeclaringType.Name + " is overridden in " + wrapper.Name);
2330
else if (baseMethod.IsStatic)
2334
else if (topPublicOrProtectedMethod == null && !baseMethod.IsPublic && !baseMethod.IsProtected && !baseMethod.DeclaringType.IsPackageAccessibleFrom(wrapper))
2336
// this is a package private method that we're not overriding (unless its vtable stream interleaves ours, which is a case we handle below)
2337
explicitOverride = true;
2339
else if (topPublicOrProtectedMethod != null && baseMethod.IsFinal && !baseMethod.IsPublic && !baseMethod.IsProtected && !baseMethod.DeclaringType.IsPackageAccessibleFrom(wrapper))
2341
// this is package private final method that we would override had it not been final, but which is ignored by HotSpot (instead of throwing a VerifyError)
2342
explicitOverride = true;
2344
else if (topPublicOrProtectedMethod == null)
2346
if (explicitOverride)
2348
List<MethodWrapper> list = new List<MethodWrapper>();
2349
list.Add(baseMethod);
2350
// we might still have to override package methods from another package if the vtable streams are interleaved with ours
2351
tw = wrapper.BaseTypeWrapper;
2354
MethodWrapper baseMethod2 = tw.GetMethodWrapper(name, sig, true);
2355
if (baseMethod2 == null || baseMethod2 == baseMethod)
2359
MethodWrapper baseMethod3 = GetPackageBaseMethod(baseMethod.DeclaringType.BaseTypeWrapper, name, sig, baseMethod2.DeclaringType);
2360
if (baseMethod3 != null)
2362
if (baseMethod2.IsFinal)
2364
baseMethod2 = baseMethod3;
2367
foreach (MethodWrapper mw in list)
2369
if (mw.DeclaringType.IsPackageAccessibleFrom(baseMethod2.DeclaringType))
2371
// we should only add each package once
2378
list.Add(baseMethod2);
2381
tw = baseMethod2.DeclaringType.BaseTypeWrapper;
2383
return list.ToArray();
2387
return new MethodWrapper[] { baseMethod };
2394
// when a package final method overrides a public or protected method, HotSpot does not mark that vtable slot as final,
2395
// so we need an explicit override to force the MethodAttributes.NewSlot flag, otherwise the CLR won't allow us
2396
// to override the original method in subsequent derived types
2397
explicitOverride = true;
2400
int majorVersion = 0;
2401
if (!baseMethod.IsPublic && !baseMethod.IsProtected &&
2402
((TryGetClassFileVersion(baseMethod.DeclaringType, ref majorVersion) && majorVersion < 51)
2403
// if TryGetClassFileVersion fails, we know that it is safe to call GetMethod() so we look at the actual method attributes here,
2404
// because access widing ensures that if the method had overridden the top level method it would also be public or protected
2405
|| (majorVersion == 0 && (LinkAndGetMethod(baseMethod).Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Assembly)))
2407
// the method we're overriding is not public or protected, but there is a public or protected top level method,
2408
// this means that baseMethod is part of a class with a major version < 51, so we have to explicitly override the top level method as well
2409
// (we don't need to look for another package method to override, because by necessity baseMethod is already in our package)
2410
return new MethodWrapper[] { baseMethod, topPublicOrProtectedMethod };
2412
else if (!topPublicOrProtectedMethod.DeclaringType.IsPackageAccessibleFrom(wrapper))
2414
// check if there is another method (in the same package) that we should override
2415
tw = topPublicOrProtectedMethod.DeclaringType.BaseTypeWrapper;
2418
MethodWrapper baseMethod2 = tw.GetMethodWrapper(name, sig, true);
2419
if (baseMethod2 == null)
2423
if (baseMethod2.IsAccessStub)
2427
else if (baseMethod2.DeclaringType.IsPackageAccessibleFrom(wrapper) && !baseMethod2.IsPrivate)
2429
if (baseMethod2.IsFinal)
2431
throw new VerifyError("final method " + baseMethod2.Name + baseMethod2.Signature + " in " + baseMethod2.DeclaringType.Name + " is overridden in " + wrapper.Name);
2433
if (!baseMethod2.IsStatic)
2435
if (baseMethod2.IsPublic || baseMethod2.IsProtected)
2439
return new MethodWrapper[] { baseMethod, baseMethod2 };
2442
tw = baseMethod2.DeclaringType.BaseTypeWrapper;
2445
return new MethodWrapper[] { baseMethod };
2447
tw = baseMethod.DeclaringType.BaseTypeWrapper;
2452
private static MethodBase LinkAndGetMethod(MethodWrapper mw)
2455
return mw.GetMethod();
2458
private static bool TryGetClassFileVersion(TypeWrapper tw, ref int majorVersion)
2460
DynamicTypeWrapper dtw = tw as DynamicTypeWrapper;
2463
JavaTypeImpl impl = dtw.impl as JavaTypeImpl;
2466
majorVersion = impl.classFile.MajorVersion;
2473
private static MethodWrapper GetPackageBaseMethod(TypeWrapper tw, string name, string sig, TypeWrapper package)
2477
MethodWrapper mw = tw.GetMethodWrapper(name, sig, true);
2482
if (mw.DeclaringType.IsPackageAccessibleFrom(package))
2484
return mw.IsFinal ? null : mw;
2486
tw = mw.DeclaringType.BaseTypeWrapper;
2491
private MethodWrapper[] FindBaseMethodsLegacy(string name, string sig, out bool explicitOverride)
2493
explicitOverride = false;
2494
TypeWrapper tw = wrapper.BaseTypeWrapper;
2497
MethodWrapper baseMethod = tw.GetMethodWrapper(name, sig, true);
2498
if (baseMethod == null)
2502
else if (baseMethod.IsAccessStub)
2506
// here are the complex rules for determining whether this method overrides the method we found
2507
// RULE 1: final methods may not be overridden
2508
// (note that we intentionally not check IsStatic here!)
2509
else if (baseMethod.IsFinal
2510
&& !baseMethod.IsPrivate
2511
&& (baseMethod.IsPublic || baseMethod.IsProtected || baseMethod.DeclaringType.IsPackageAccessibleFrom(wrapper)))
2513
throw new VerifyError("final method " + baseMethod.Name + baseMethod.Signature + " in " + baseMethod.DeclaringType.Name + " is overridden in " + wrapper.Name);
2515
// RULE 1a: static methods are ignored (other than the RULE 1 check)
2516
else if (baseMethod.IsStatic)
2519
// RULE 2: public & protected methods can be overridden (package methods are handled by RULE 4)
2520
// (by public, protected & *package* methods [even if they are in a different package])
2521
else if (baseMethod.IsPublic || baseMethod.IsProtected)
2523
// if we already encountered a package method, we cannot override the base method of
2524
// that package method
2525
if (explicitOverride)
2527
explicitOverride = false;
2530
if (!baseMethod.DeclaringType.IsPackageAccessibleFrom(wrapper))
2532
// check if there is another method (in the same package) that we should override
2533
tw = baseMethod.DeclaringType.BaseTypeWrapper;
2536
MethodWrapper baseMethod2 = tw.GetMethodWrapper(name, sig, true);
2537
if (baseMethod2 == null)
2541
if (baseMethod2.IsAccessStub)
2545
else if (baseMethod2.DeclaringType.IsPackageAccessibleFrom(wrapper) && !baseMethod2.IsPrivate)
2547
if (baseMethod2.IsFinal)
2549
throw new VerifyError("final method " + baseMethod2.Name + baseMethod2.Signature + " in " + baseMethod2.DeclaringType.Name + " is overridden in " + wrapper.Name);
2551
if (!baseMethod2.IsStatic)
2553
if (baseMethod2.IsPublic || baseMethod2.IsProtected)
2557
return new MethodWrapper[] { baseMethod, baseMethod2 };
2560
tw = baseMethod2.DeclaringType.BaseTypeWrapper;
2563
return new MethodWrapper[] { baseMethod };
2565
// RULE 3: private and static methods are ignored
2566
else if (!baseMethod.IsPrivate)
2568
// RULE 4: package methods can only be overridden in the same package
2569
if (baseMethod.DeclaringType.IsPackageAccessibleFrom(wrapper)
2570
|| (baseMethod.IsInternal && baseMethod.DeclaringType.InternalsVisibleTo(wrapper)))
2572
return new MethodWrapper[] { baseMethod };
2574
// since we encountered a method with the same name/signature that we aren't overriding,
2575
// we need to specify an explicit override
2576
// NOTE we only do this if baseMethod isn't private, because if it is, Reflection.Emit
2577
// will complain about the explicit MethodOverride (possibly a bug)
2578
explicitOverride = true;
2580
tw = baseMethod.DeclaringType.BaseTypeWrapper;
2585
private static MethodInfo GetBaseFinalizeMethod(TypeWrapper wrapper)
2589
// HACK we get called during method linking (which is probably a bad idea) and
2590
// it is possible for the base type not to be finished yet, so we look at the
2591
// private state of the unfinished base types to find the finalize method.
2592
DynamicTypeWrapper dtw = wrapper as DynamicTypeWrapper;
2597
MethodWrapper mw = dtw.GetMethodWrapper(StringConstants.FINALIZE, StringConstants.SIG_VOID, false);
2602
MethodInfo finalizeImpl = dtw.impl.GetFinalizeMethod();
2603
if (finalizeImpl != null)
2605
return finalizeImpl;
2607
wrapper = wrapper.BaseTypeWrapper;
2609
if (wrapper == CoreClasses.java.lang.Object.Wrapper || wrapper == CoreClasses.java.lang.Throwable.Wrapper)
2611
return Types.Object.GetMethod("Finalize", BindingFlags.NonPublic | BindingFlags.Instance);
2613
Type type = wrapper.TypeAsBaseType;
2614
MethodInfo baseFinalize = type.GetMethod("__<Finalize>", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, null, Type.EmptyTypes, null);
2615
if (baseFinalize != null)
2617
return baseFinalize;
2619
while (type != null)
2621
foreach (MethodInfo m in type.GetMethods(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly))
2623
if (m.Name == "Finalize"
2624
&& m.ReturnType == Types.Void
2625
&& m.GetParameters().Length == 0)
2627
if (m.GetBaseDefinition().DeclaringType == Types.Object)
2633
type = type.BaseType;
2638
private MethodAttributes GetPropertyAccess(MethodWrapper mw)
2640
string sig = mw.ReturnType.SigName;
2643
sig = mw.GetParameters()[0].SigName;
2646
foreach (ClassFile.Field field in classFile.Fields)
2648
if (field.IsProperty
2649
&& field.IsStatic == mw.IsStatic
2650
&& field.Signature == sig
2651
&& (field.PropertyGetter == mw.Name || field.PropertySetter == mw.Name))
2658
else if (field.IsProtected)
2662
else if (field.IsPrivate)
2679
return MethodAttributes.Private;
2681
return MethodAttributes.Assembly;
2683
return MethodAttributes.FamORAssem;
2685
return MethodAttributes.Public;
2687
throw new InvalidOperationException();
2691
internal override MethodBase LinkMethod(MethodWrapper mw)
2693
if (mw is DelegateConstructorMethodWrapper)
2695
((DelegateConstructorMethodWrapper)mw).DoLink(typeBuilder);
2698
if (mw is DelegateInvokeStubMethodWrapper)
2700
return ((DelegateInvokeStubMethodWrapper)mw).DoLink(typeBuilder);
2702
Debug.Assert(mw != null);
2703
int index = GetMethodIndex(mw);
2704
if (baseMethods[index] != null)
2706
foreach (MethodWrapper baseMethod in baseMethods[index])
2709
CheckLoaderConstraints(mw, baseMethod);
2712
Debug.Assert(mw.GetMethod() == null);
2713
methods[index].AssertLinked();
2714
Profiler.Enter("JavaTypeImpl.GenerateMethod");
2717
if (index >= classFile.Methods.Length)
2719
if (methods[index].IsMirandaMethod)
2721
// We're a Miranda method
2722
Debug.Assert(baseMethods[index].Length == 1 && baseMethods[index][0].DeclaringType.IsInterface);
2723
MethodBuilder mb = methods[index].GetDefineMethodHelper().DefineMethod(wrapper, typeBuilder, methods[index].Name, MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.Abstract | MethodAttributes.CheckAccessOnOverride);
2724
AttributeHelper.HideFromReflection(mb);
2725
if (CheckRequireOverrideStub(methods[index], baseMethods[index][0]))
2727
wrapper.GenerateOverrideStub(typeBuilder, baseMethods[index][0], mb, methods[index]);
2729
// if we changed the name or if the interface method name is remapped, we need to add an explicit methodoverride.
2730
else if (!baseMethods[index][0].IsDynamicOnly && methods[index].Name != baseMethods[index][0].RealName)
2732
typeBuilder.DefineMethodOverride(mb, (MethodInfo)baseMethods[index][0].GetMethod());
2738
throw new InvalidOperationException();
2741
ClassFile.Method m = classFile.Methods[index];
2742
MethodBuilder method;
2743
bool setModifiers = false;
2744
if (methods[index].HasCallerID && (m.Modifiers & Modifiers.VarArgs) != 0)
2746
// the implicit callerID parameter was added at the end so that means we shouldn't use ParamArrayAttribute,
2747
// so we need to explicitly record that the method is varargs
2748
setModifiers = true;
2750
if (m.IsConstructor)
2752
method = GenerateConstructor(methods[index]);
2753
// strictfp is the only modifier that a constructor can have
2756
setModifiers = true;
2759
else if (m.IsClassInitializer)
2761
method = ReflectUtil.DefineTypeInitializer(typeBuilder);
2765
method = GenerateMethod(index, m, ref setModifiers);
2767
string[] exceptions = m.ExceptionsAttribute;
2768
methods[index].SetDeclaredExceptions(exceptions);
2770
AttributeHelper.SetThrowsAttribute(method, exceptions);
2771
if (setModifiers || m.IsInternal || (m.Modifiers & (Modifiers.Synthetic | Modifiers.Bridge)) != 0)
2773
AttributeHelper.SetModifiers(method, m.Modifiers, m.IsInternal);
2775
if ((m.Modifiers & (Modifiers.Synthetic | Modifiers.Bridge)) != 0
2776
&& (m.IsPublic || m.IsProtected)
2778
&& !IsAccessBridge(classFile, m))
2780
AttributeHelper.SetEditorBrowsableNever(method);
2781
// TODO on WHIDBEY apply CompilerGeneratedAttribute
2783
if (m.DeprecatedAttribute)
2785
AttributeHelper.SetDeprecatedAttribute(method);
2787
if (m.GenericSignature != null)
2789
AttributeHelper.SetSignatureAttribute(method, m.GenericSignature);
2791
#else // STATIC_COMPILER
2794
// shut up the compiler
2796
#endif // STATIC_COMPILER
2801
Profiler.Leave("JavaTypeImpl.GenerateMethod");
2805
private MethodBuilder GenerateConstructor(MethodWrapper mw)
2807
MethodBuilder cb = mw.GetDefineMethodHelper().DefineConstructor(wrapper, typeBuilder, GetMethodAccess(mw) | MethodAttributes.HideBySig);
2808
cb.SetImplementationFlags(MethodImplAttributes.NoInlining);
2812
private MethodBuilder GenerateMethod(int index, ClassFile.Method m, ref bool setModifiers)
2814
MethodAttributes attribs = MethodAttributes.HideBySig;
2817
if (wrapper.IsPInvokeMethod(m))
2819
// this doesn't appear to be necessary, but we use the flag in Finish to know
2820
// that we shouldn't emit a method body
2821
attribs |= MethodAttributes.PinvokeImpl;
2825
setModifiers = true;
2828
if (methods[index].IsPropertyAccessor)
2830
attribs |= GetPropertyAccess(methods[index]);
2831
attribs |= MethodAttributes.SpecialName;
2832
setModifiers = true;
2836
attribs |= GetMethodAccess(methods[index]);
2840
// only if the classfile is abstract, we make the CLR method abstract, otherwise,
2841
// we have to generate a method that throws an AbstractMethodError (because the JVM
2842
// allows abstract methods in non-abstract classes)
2843
if (classFile.IsAbstract)
2845
if (classFile.IsPublic && !classFile.IsFinal && !(m.IsPublic || m.IsProtected))
2847
setModifiers = true;
2851
attribs |= MethodAttributes.Abstract;
2856
setModifiers = true;
2861
if (!m.IsStatic && !m.IsPrivate)
2863
attribs |= MethodAttributes.Final;
2867
setModifiers = true;
2872
attribs |= MethodAttributes.Static;
2873
if (m.IsSynchronized)
2875
setModifiers = true;
2878
else if (!m.IsPrivate)
2880
attribs |= MethodAttributes.Virtual | MethodAttributes.CheckAccessOnOverride;
2882
string name = m.Name;
2884
if ((m.Modifiers & Modifiers.Bridge) != 0 && (m.IsPublic || m.IsProtected) && wrapper.IsPublic)
2886
string sigbase = m.Signature.Substring(0, m.Signature.LastIndexOf(')') + 1);
2887
foreach (MethodWrapper mw in methods)
2889
if (mw.Name == m.Name && mw.Signature.StartsWith(sigbase) && mw.Signature != m.Signature)
2891
// To prevent bridge methods with covariant return types from confusing
2892
// other .NET compilers (like C#), we rename the bridge method.
2893
name = NamePrefix.Bridge + name;
2899
if ((attribs & MethodAttributes.Virtual) != 0 && !classFile.IsInterface)
2901
if (baseMethods[index] == null || (baseMethods[index].Length == 1 && baseMethods[index][0].DeclaringType.IsInterface))
2903
// we need to set NewSlot here, to prevent accidentally overriding methods
2904
// (for example, if a Java class has a method "boolean Equals(object)", we don't want that method
2905
// to override System.Object.Equals)
2906
attribs |= MethodAttributes.NewSlot;
2910
// if we have a method overriding a more accessible method (the JVM allows this), we need to make the
2911
// method more accessible, because otherwise the CLR will complain that we're reducing access
2912
bool hasPublicBaseMethod = false;
2913
foreach (MethodWrapper baseMethodWrapper in baseMethods[index])
2915
MethodBase baseMethod = baseMethodWrapper.GetMethod();
2916
if ((baseMethod.IsPublic && !m.IsPublic) ||
2917
((baseMethod.IsFamily || baseMethod.IsFamilyOrAssembly) && !m.IsPublic && !m.IsProtected) ||
2918
(!m.IsPublic && !m.IsProtected && !baseMethodWrapper.DeclaringType.IsPackageAccessibleFrom(wrapper)))
2920
hasPublicBaseMethod |= baseMethod.IsPublic;
2921
attribs &= ~MethodAttributes.MemberAccessMask;
2922
attribs |= hasPublicBaseMethod ? MethodAttributes.Public : MethodAttributes.FamORAssem;
2923
setModifiers = true;
2928
MethodBuilder mb = null;
2930
mb = wrapper.DefineGhostMethod(name, attribs, methods[index]);
2934
bool needFinalize = false;
2935
bool needDispatch = false;
2936
MethodInfo baseFinalize = null;
2937
if (baseMethods[index] != null && ReferenceEquals(m.Name, StringConstants.FINALIZE) && ReferenceEquals(m.Signature, StringConstants.SIG_VOID))
2939
baseFinalize = GetBaseFinalizeMethod(wrapper.BaseTypeWrapper);
2940
if (baseMethods[index][0].DeclaringType == CoreClasses.java.lang.Object.Wrapper)
2942
// This type is the first type in the hierarchy to introduce a finalize method
2943
// (other than the one in java.lang.Object obviously), so we need to override
2944
// the real Finalize method and emit a dispatch call to our finalize method.
2945
needFinalize = true;
2946
needDispatch = true;
2950
// One of our base classes already has a finalize method, so we already are
2951
// hooked into the real Finalize, but we need to override it again, to make it
2952
// final (so that non-Java types cannot override it either).
2953
needFinalize = true;
2954
needDispatch = false;
2955
// If the base class finalize was optimized away, we need a dispatch call after all.
2956
if (baseFinalize.DeclaringType == Types.Object)
2958
needDispatch = true;
2963
// One of our base classes already has a finalize method, but it may have been an empty
2964
// method so that the hookup to the real Finalize was optimized away, we need to check
2966
if (baseFinalize.DeclaringType == Types.Object)
2968
needFinalize = true;
2969
needDispatch = true;
2973
!m.IsAbstract && !m.IsNative &&
2974
(!m.IsFinal || classFile.IsFinal) &&
2975
m.Instructions.Length > 0 &&
2976
m.Instructions[0].NormalizedOpCode == NormalizedByteCode.__return)
2978
// we've got an empty finalize method, so we don't need to override the real finalizer
2979
// (not having a finalizer makes a huge perf difference)
2980
needFinalize = false;
2983
bool newslot = baseMethods[index] != null
2984
&& (methods[index].IsExplicitOverride || baseMethods[index][0].RealName != name || CheckRequireOverrideStub(methods[index], baseMethods[index][0]))
2988
attribs |= MethodAttributes.NewSlot;
2990
mb = methods[index].GetDefineMethodHelper().DefineMethod(wrapper, typeBuilder, name, attribs);
2991
if (baseMethods[index] != null && !needFinalize)
2993
bool subsequent = false;
2994
foreach (MethodWrapper baseMethod in baseMethods[index])
2996
if (CheckRequireOverrideStub(methods[index], baseMethod))
2998
wrapper.GenerateOverrideStub(typeBuilder, baseMethod, mb, methods[index]);
3000
else if (subsequent || methods[index].IsExplicitOverride || baseMethod.RealName != name)
3002
typeBuilder.DefineMethodOverride(mb, (MethodInfo)baseMethod.GetMethod());
3004
// the non-primary base methods always need an explicit method override
3008
// if we're overriding java.lang.Object.finalize we need to emit a stub to override System.Object.Finalize,
3009
// or if we're subclassing a non-Java class that has a Finalize method, we need a new Finalize override
3012
string finalizeName = baseFinalize.Name;
3013
MethodWrapper mwClash = wrapper.GetMethodWrapper(finalizeName, StringConstants.SIG_VOID, true);
3014
if (mwClash != null && mwClash.GetMethod() != baseFinalize)
3016
finalizeName = "__<Finalize>";
3018
MethodAttributes attr = MethodAttributes.HideBySig | MethodAttributes.Virtual;
3019
// make sure we don't reduce accessibility
3020
attr |= baseFinalize.IsPublic ? MethodAttributes.Public : MethodAttributes.Family;
3023
attr |= MethodAttributes.Final;
3025
finalizeMethod = typeBuilder.DefineMethod(finalizeName, attr, CallingConventions.Standard, Types.Void, Type.EmptyTypes);
3026
if (finalizeName != baseFinalize.Name)
3028
typeBuilder.DefineMethodOverride(finalizeMethod, baseFinalize);
3030
AttributeHelper.HideFromJava(finalizeMethod);
3031
CodeEmitter ilgen = CodeEmitter.Create(finalizeMethod);
3032
ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.SkipFinalizer);
3033
CodeEmitterLabel skip = ilgen.DefineLabel();
3034
ilgen.EmitBrtrue(skip);
3037
ilgen.BeginExceptionBlock();
3038
ilgen.Emit(OpCodes.Ldarg_0);
3039
ilgen.Emit(OpCodes.Callvirt, mb);
3040
ilgen.EmitLeave(skip);
3041
ilgen.BeginCatchBlock(Types.Object);
3042
ilgen.EmitLeave(skip);
3043
ilgen.EndExceptionBlock();
3047
ilgen.Emit(OpCodes.Ldarg_0);
3048
ilgen.Emit(OpCodes.Call, baseFinalize);
3050
ilgen.MarkLabel(skip);
3051
ilgen.Emit(OpCodes.Ret);
3055
if (classFile.Methods[index].AnnotationDefault != null)
3057
CustomAttributeBuilder cab = new CustomAttributeBuilder(StaticCompiler.GetRuntimeType("IKVM.Attributes.AnnotationDefaultAttribute").GetConstructor(new Type[] { Types.Object }), new object[] { classFile.Methods[index].AnnotationDefault });
3058
mb.SetCustomAttribute(cab);
3060
#endif // STATIC_COMPILER
3063
if ((methods[index].Modifiers & (Modifiers.Synchronized | Modifiers.Static)) == Modifiers.Synchronized)
3065
mb.SetImplementationFlags(mb.GetMethodImplementationFlags() | MethodImplAttributes.Synchronized);
3071
private static MethodAttributes GetMethodAccess(MethodWrapper mw)
3073
switch (mw.Modifiers & Modifiers.AccessMask)
3075
case Modifiers.Private:
3076
return MethodAttributes.Private;
3077
case Modifiers.Protected:
3078
return MethodAttributes.FamORAssem;
3079
case Modifiers.Public:
3080
return MethodAttributes.Public;
3082
return MethodAttributes.Assembly;
3087
// The classic example of an access bridge is StringBuilder.length(), the JDK 6 compiler
3088
// generates this to work around a reflection problem (which otherwise wouldn't surface the
3089
// length() method, because it is defined in the non-public base class AbstractStringBuilder.)
3090
private static bool IsAccessBridge(ClassFile classFile, ClassFile.Method m)
3092
// HACK this is a pretty gross hack
3093
// We look at the method body to figure out if the bridge method calls another method with the exact
3094
// same name/signature and if that is the case, we assume that it is an access bridge.
3095
// This code is based on the javac algorithm in addBridgeIfNeeded(...) in com/sun/tools/javac/comp/TransTypes.java.
3096
if ((m.Modifiers & (Modifiers.Abstract | Modifiers.Native | Modifiers.Public | Modifiers.Bridge)) == (Modifiers.Public | Modifiers.Bridge))
3098
foreach (ClassFile.Method.Instruction instr in m.Instructions)
3100
if (instr.NormalizedOpCode == NormalizedByteCode.__invokespecial)
3102
ClassFile.ConstantPoolItemMI cpi = classFile.SafeGetMethodref(instr.Arg1);
3103
return cpi != null && cpi.Name == m.Name && cpi.Signature == m.Signature;
3109
#endif // STATIC_COMPILER
3111
internal override Type Type
3119
internal override string GetGenericSignature()
3121
Debug.Fail("Unreachable code");
3125
internal override string[] GetEnclosingMethod()
3127
Debug.Fail("Unreachable code");
3131
internal override string GetGenericMethodSignature(int index)
3133
Debug.Fail("Unreachable code");
3137
internal override string GetGenericFieldSignature(int index)
3139
Debug.Fail("Unreachable code");
3143
internal override object[] GetDeclaredAnnotations()
3145
Debug.Fail("Unreachable code");
3149
internal override object GetMethodDefaultValue(int index)
3151
Debug.Fail("Unreachable code");
3155
internal override object[] GetMethodAnnotations(int index)
3157
Debug.Fail("Unreachable code");
3161
internal override object[][] GetParameterAnnotations(int index)
3163
Debug.Fail("Unreachable code");
3167
internal override object[] GetFieldAnnotations(int index)
3169
Debug.Fail("Unreachable code");
3173
internal override MethodInfo GetFinalizeMethod()
3175
return finalizeMethod;
3179
private sealed class Metadata
3181
private string[][] genericMetaData;
3182
private object[][] annotations;
3184
private Metadata(string[][] genericMetaData, object[][] annotations)
3186
this.genericMetaData = genericMetaData;
3187
this.annotations = annotations;
3190
internal static Metadata Create(ClassFile classFile)
3192
if (classFile.MajorVersion < 49)
3196
string[][] genericMetaData = null;
3197
object[][] annotations = null;
3198
for (int i = 0; i < classFile.Methods.Length; i++)
3200
if (classFile.Methods[i].GenericSignature != null)
3202
if (genericMetaData == null)
3204
genericMetaData = new string[4][];
3206
if (genericMetaData[0] == null)
3208
genericMetaData[0] = new string[classFile.Methods.Length];
3210
genericMetaData[0][i] = classFile.Methods[i].GenericSignature;
3212
if (classFile.Methods[i].Annotations != null)
3214
if (annotations == null)
3216
annotations = new object[5][];
3218
if (annotations[1] == null)
3220
annotations[1] = new object[classFile.Methods.Length];
3222
annotations[1][i] = classFile.Methods[i].Annotations;
3224
if (classFile.Methods[i].ParameterAnnotations != null)
3226
if (annotations == null)
3228
annotations = new object[5][];
3230
if (annotations[2] == null)
3232
annotations[2] = new object[classFile.Methods.Length];
3234
annotations[2][i] = classFile.Methods[i].ParameterAnnotations;
3236
if (classFile.Methods[i].AnnotationDefault != null)
3238
if (annotations == null)
3240
annotations = new object[5][];
3242
if (annotations[3] == null)
3244
annotations[3] = new object[classFile.Methods.Length];
3246
annotations[3][i] = classFile.Methods[i].AnnotationDefault;
3249
for (int i = 0; i < classFile.Fields.Length; i++)
3251
if (classFile.Fields[i].GenericSignature != null)
3253
if (genericMetaData == null)
3255
genericMetaData = new string[4][];
3257
if (genericMetaData[1] == null)
3259
genericMetaData[1] = new string[classFile.Fields.Length];
3261
genericMetaData[1][i] = classFile.Fields[i].GenericSignature;
3263
if (classFile.Fields[i].Annotations != null)
3265
if (annotations == null)
3267
annotations = new object[5][];
3269
if (annotations[4] == null)
3271
annotations[4] = new object[classFile.Fields.Length][];
3273
annotations[4][i] = classFile.Fields[i].Annotations;
3276
if (classFile.EnclosingMethod != null)
3278
if (genericMetaData == null)
3280
genericMetaData = new string[4][];
3282
genericMetaData[2] = classFile.EnclosingMethod;
3284
if (classFile.GenericSignature != null)
3286
if (genericMetaData == null)
3288
genericMetaData = new string[4][];
3290
genericMetaData[3] = new string[] { classFile.GenericSignature };
3292
if (classFile.Annotations != null)
3294
if (annotations == null)
3296
annotations = new object[5][];
3298
annotations[0] = classFile.Annotations;
3300
if (genericMetaData != null || annotations != null)
3302
return new Metadata(genericMetaData, annotations);
3307
internal static string GetGenericSignature(Metadata m)
3309
if (m != null && m.genericMetaData != null && m.genericMetaData[3] != null)
3311
return m.genericMetaData[3][0];
3316
internal static string[] GetEnclosingMethod(Metadata m)
3318
if (m != null && m.genericMetaData != null)
3320
return m.genericMetaData[2];
3325
internal static string GetGenericMethodSignature(Metadata m, int index)
3327
if (m != null && m.genericMetaData != null && m.genericMetaData[0] != null)
3329
return m.genericMetaData[0][index];
3334
internal static string GetGenericFieldSignature(Metadata m, int index)
3336
if (m != null && m.genericMetaData != null && m.genericMetaData[1] != null)
3338
return m.genericMetaData[1][index];
3343
internal static object[] GetAnnotations(Metadata m)
3345
if (m != null && m.annotations != null)
3347
return m.annotations[0];
3352
internal static object[] GetMethodAnnotations(Metadata m, int index)
3354
if (m != null && m.annotations != null && m.annotations[1] != null)
3356
return (object[])m.annotations[1][index];
3361
internal static object[][] GetMethodParameterAnnotations(Metadata m, int index)
3363
if (m != null && m.annotations != null && m.annotations[2] != null)
3365
return (object[][])m.annotations[2][index];
3370
internal static object GetMethodDefaultValue(Metadata m, int index)
3372
if (m != null && m.annotations != null && m.annotations[3] != null)
3374
return m.annotations[3][index];
3379
// note that unlike GetGenericFieldSignature, the index is simply the field index
3380
internal static object[] GetFieldAnnotations(Metadata m, int index)
3382
if (m != null && m.annotations != null && m.annotations[4] != null)
3384
return (object[])m.annotations[4][index];
3390
private sealed class FinishedTypeImpl : DynamicImpl
3393
private TypeWrapper[] innerclasses;
3394
private TypeWrapper declaringTypeWrapper;
3395
private Modifiers reflectiveModifiers;
3396
private MethodInfo clinitMethod;
3397
private MethodInfo finalizeMethod;
3398
private Metadata metadata;
3400
internal FinishedTypeImpl(Type type, TypeWrapper[] innerclasses, TypeWrapper declaringTypeWrapper, Modifiers reflectiveModifiers, Metadata metadata, MethodInfo clinitMethod, MethodInfo finalizeMethod)
3403
this.innerclasses = innerclasses;
3404
this.declaringTypeWrapper = declaringTypeWrapper;
3405
this.reflectiveModifiers = reflectiveModifiers;
3406
this.clinitMethod = clinitMethod;
3407
this.finalizeMethod = finalizeMethod;
3408
this.metadata = metadata;
3411
internal override TypeWrapper[] InnerClasses
3415
// TODO compute the innerclasses lazily (and fix JavaTypeImpl to not always compute them)
3416
return innerclasses;
3420
internal override TypeWrapper DeclaringTypeWrapper
3424
// TODO compute lazily (and fix JavaTypeImpl to not always compute it)
3425
return declaringTypeWrapper;
3429
internal override Modifiers ReflectiveModifiers
3433
return reflectiveModifiers;
3437
internal override Type Type
3445
internal override void EmitRunClassConstructor(CodeEmitter ilgen)
3447
if (clinitMethod != null)
3449
ilgen.Emit(OpCodes.Call, clinitMethod);
3453
internal override DynamicImpl Finish()
3458
internal override MethodBase LinkMethod(MethodWrapper mw)
3460
// we should never be called, because all methods on a finished type are already linked
3461
Debug.Assert(false);
3462
return mw.GetMethod();
3465
internal override FieldInfo LinkField(FieldWrapper fw)
3467
// we should never be called, because all fields on a finished type are already linked
3468
Debug.Assert(false);
3469
return fw.GetField();
3472
internal override string GetGenericSignature()
3474
return Metadata.GetGenericSignature(metadata);
3477
internal override string[] GetEnclosingMethod()
3479
return Metadata.GetEnclosingMethod(metadata);
3482
internal override string GetGenericMethodSignature(int index)
3484
return Metadata.GetGenericMethodSignature(metadata, index);
3487
internal override string GetGenericFieldSignature(int index)
3489
return Metadata.GetGenericFieldSignature(metadata, index);
3492
internal override object[] GetDeclaredAnnotations()
3494
return Metadata.GetAnnotations(metadata);
3497
internal override object GetMethodDefaultValue(int index)
3499
return Metadata.GetMethodDefaultValue(metadata, index);
3502
internal override object[] GetMethodAnnotations(int index)
3504
return Metadata.GetMethodAnnotations(metadata, index);
3507
internal override object[][] GetParameterAnnotations(int index)
3509
return Metadata.GetMethodParameterAnnotations(metadata, index);
3512
internal override object[] GetFieldAnnotations(int index)
3514
return Metadata.GetFieldAnnotations(metadata, index);
3517
internal override MethodInfo GetFinalizeMethod()
3519
return finalizeMethod;
3523
internal sealed class FinishContext
3525
private readonly ClassFile classFile;
3526
private readonly DynamicOrAotTypeWrapper wrapper;
3527
private readonly TypeBuilder typeBuilder;
3528
private List<TypeBuilder> nestedTypeBuilders;
3529
private MethodInfo callerIDMethod;
3530
private List<Item> items;
3531
private Dictionary<FieldWrapper, MethodBuilder> arfuMap;
3536
internal object value;
3539
internal FinishContext(ClassFile classFile, DynamicOrAotTypeWrapper wrapper, TypeBuilder typeBuilder)
3541
this.classFile = classFile;
3542
this.wrapper = wrapper;
3543
this.typeBuilder = typeBuilder;
3546
internal T GetValue<T>(int key)
3547
where T : class, new()
3551
items = new List<Item>();
3553
for (int i = 0; i < items.Count; i++)
3556
if (items[i].key == key && (value = items[i].value as T) != null)
3569
internal void EmitCallerID(CodeEmitter ilgen)
3571
if (callerIDMethod == null)
3573
CreateGetCallerID();
3575
ilgen.Emit(OpCodes.Call, callerIDMethod);
3578
private void CreateGetCallerID()
3580
TypeWrapper tw = CoreClasses.ikvm.@internal.CallerID.Wrapper;
3581
FieldBuilder callerIDField = typeBuilder.DefineField("__<callerID>", tw.TypeAsSignatureType, FieldAttributes.Private | FieldAttributes.Static | FieldAttributes.SpecialName);
3582
MethodBuilder mb = typeBuilder.DefineMethod("__<GetCallerID>", MethodAttributes.Private | MethodAttributes.Static | MethodAttributes.SpecialName, tw.TypeAsSignatureType, Type.EmptyTypes);
3583
callerIDMethod = mb;
3584
CodeEmitter ilgen = CodeEmitter.Create(mb);
3585
ilgen.Emit(OpCodes.Ldsfld, callerIDField);
3586
CodeEmitterLabel done = ilgen.DefineLabel();
3587
ilgen.EmitBrtrue(done);
3588
EmitCallerIDInitialization(ilgen, callerIDField);
3589
ilgen.MarkLabel(done);
3590
ilgen.Emit(OpCodes.Ldsfld, callerIDField);
3591
ilgen.Emit(OpCodes.Ret);
3595
private void RegisterNestedTypeBuilder(TypeBuilder tb)
3597
if (nestedTypeBuilders == null)
3599
nestedTypeBuilders = new List<TypeBuilder>();
3601
nestedTypeBuilders.Add(tb);
3604
internal Type FinishImpl()
3606
MethodWrapper[] methods = wrapper.GetMethods();
3607
FieldWrapper[] fields = wrapper.GetFields();
3609
wrapper.FinishGhost(typeBuilder, methods);
3610
#endif // STATIC_COMPILER
3612
if (!classFile.IsInterface)
3614
// set the base type (this needs to be done before we emit any methods, because in the static compiler
3615
// GetBaseTypeForDefineType() has the side effect of inserting the __WorkaroundBaseClass__ when necessary)
3616
typeBuilder.SetParent(wrapper.GetBaseTypeForDefineType());
3619
// if we're not abstract make sure we don't inherit any abstract methods
3620
if (!wrapper.IsAbstract)
3622
TypeWrapper parent = wrapper.BaseTypeWrapper;
3623
// if parent is not abstract, the .NET implementation will never have abstract methods (only
3624
// stubs that throw AbstractMethodError)
3625
// NOTE interfaces are supposed to be abstract, but the VM doesn't enforce this, so
3626
// we have to check for a null parent (interfaces have no parent).
3627
while (parent != null && parent.IsAbstract)
3629
foreach (MethodWrapper mw in parent.GetMethods())
3631
MethodInfo mi = mw.GetMethod() as MethodInfo;
3632
if (mi != null && mi.IsAbstract && !mi.DeclaringType.IsInterface)
3634
bool needStub = false;
3635
bool needRename = false;
3636
if (mw.IsPublic || mw.IsProtected)
3638
MethodWrapper fmw = wrapper.GetMethodWrapper(mw.Name, mw.Signature, true);
3639
while (fmw != mw && (fmw.IsStatic || fmw.IsPrivate))
3642
fmw = fmw.DeclaringType.BaseTypeWrapper.GetMethodWrapper(mw.Name, mw.Signature, true);
3644
if (fmw == mw && fmw.DeclaringType != wrapper)
3651
MethodWrapper fmw = wrapper.GetMethodWrapper(mw.Name, mw.Signature, true);
3652
while (fmw != mw && (fmw.IsStatic || fmw.IsPrivate || !(mw.DeclaringType.IsPackageAccessibleFrom(fmw.DeclaringType) || (mw.IsInternal && mw.DeclaringType.InternalsVisibleTo(fmw.DeclaringType)))))
3655
fmw = fmw.DeclaringType.BaseTypeWrapper.GetMethodWrapper(mw.Name, mw.Signature, true);
3657
if (fmw == mw && fmw.DeclaringType != wrapper)
3664
// NOTE in Sun's JRE 1.4.1 this method cannot be overridden by subclasses,
3665
// but I think this is a bug, so we'll support it anyway.
3666
string name = mi.Name;
3667
MethodAttributes attr = mi.Attributes & ~(MethodAttributes.Abstract | MethodAttributes.NewSlot);
3670
name = "__<>" + name + "/" + mi.DeclaringType.FullName;
3671
attr = MethodAttributes.Private | MethodAttributes.Virtual | MethodAttributes.NewSlot;
3673
MethodBuilder mb = mw.GetDefineMethodHelper().DefineMethod(wrapper, typeBuilder, name, attr);
3676
typeBuilder.DefineMethodOverride(mb, mi);
3678
AttributeHelper.HideFromJava(mb);
3679
CodeEmitter ilgen = CodeEmitter.Create(mb);
3680
ilgen.EmitThrow("java.lang.AbstractMethodError", mw.DeclaringType.Name + "." + mw.Name + mw.Signature);
3685
parent = parent.BaseTypeWrapper;
3688
Dictionary<MethodKey, MethodInfo> invokespecialstubcache = new Dictionary<MethodKey, MethodInfo>();
3689
bool basehasclinit = wrapper.BaseTypeWrapper != null && wrapper.BaseTypeWrapper.HasStaticInitializer;
3690
int clinitIndex = -1;
3691
bool hasConstructor = false;
3692
for (int i = 0; i < classFile.Methods.Length; i++)
3694
ClassFile.Method m = classFile.Methods[i];
3695
MethodBuilder mb = (MethodBuilder)methods[i].GetMethod();
3698
// method doesn't really exist (e.g. delegate constructor or <clinit> that is optimized away)
3699
if (m.IsConstructor)
3701
hasConstructor = true;
3704
else if (m.IsClassInitializer)
3706
// we handle the <clinit> after we've done the other methods,
3707
// to make it easier to inject code needed by the other methods
3711
else if (m.IsConstructor)
3713
hasConstructor = true;
3714
CodeEmitter ilGenerator = CodeEmitter.Create(mb);
3715
CompileConstructorBody(this, ilGenerator, i, invokespecialstubcache);
3722
if (!classFile.IsAbstract)
3724
// NOTE in the JVM it is apparently legal for a non-abstract class to have abstract methods, but
3725
// the CLR doens't allow this, so we have to emit a method that throws an AbstractMethodError
3728
else if (classFile.IsPublic && !classFile.IsFinal && !(m.IsPublic || m.IsProtected))
3730
// We have an abstract package accessible method in our public class. To allow a class in another
3731
// assembly to subclass this class, we must fake the abstractness of this method.
3736
CodeEmitter ilGenerator = CodeEmitter.Create(mb);
3737
TraceHelper.EmitMethodTrace(ilGenerator, classFile.Name + "." + m.Name + m.Signature);
3738
ilGenerator.EmitThrow("java.lang.AbstractMethodError", classFile.Name + "." + m.Name + m.Signature);
3739
ilGenerator.DoEmit();
3742
else if (m.IsNative)
3744
if ((mb.Attributes & MethodAttributes.PinvokeImpl) != 0)
3748
if (wrapper.IsDelegate)
3750
mb.SetImplementationFlags(mb.GetMethodImplementationFlags() | MethodImplAttributes.Runtime);
3753
Profiler.Enter("JavaTypeImpl.Finish.Native");
3756
CodeEmitter ilGenerator = CodeEmitter.Create(mb);
3757
TraceHelper.EmitMethodTrace(ilGenerator, classFile.Name + "." + m.Name + m.Signature);
3759
// do we have an implementation in map.xml?
3760
if (wrapper.EmitMapXmlMethodPrologueAndOrBody(ilGenerator, classFile, m))
3762
ilGenerator.DoEmit();
3766
// see if there exists a "managed JNI" class for this type
3767
Type nativeCodeType = null;
3769
nativeCodeType = StaticCompiler.GetType(wrapper.GetClassLoader(), "IKVM.NativeCode." + classFile.Name.Replace('$', '+'));
3770
if (nativeCodeType == null)
3772
// simple JNI like class name mangling
3773
nativeCodeType = StaticCompiler.GetType(wrapper.GetClassLoader(), "Java_" + classFile.Name.Replace('.', '_'));
3776
MethodInfo nativeMethod = null;
3777
TypeWrapper[] args = methods[i].GetParameters();
3778
if (nativeCodeType != null)
3780
TypeWrapper[] nargs = args;
3783
nargs = new TypeWrapper[args.Length + 1];
3784
args.CopyTo(nargs, 1);
3785
nargs[0] = this.wrapper;
3787
MethodInfo[] nativeCodeTypeMethods = nativeCodeType.GetMethods(BindingFlags.Static | BindingFlags.Public);
3788
foreach (MethodInfo method in nativeCodeTypeMethods)
3790
ParameterInfo[] param = method.GetParameters();
3791
TypeWrapper[] match = new TypeWrapper[param.Length];
3792
for (int j = 0; j < param.Length; j++)
3794
match[j] = ClassLoaderWrapper.GetWrapperFromType(param[j].ParameterType);
3796
if (m.Name == method.Name && IsCompatibleArgList(nargs, match))
3798
// TODO instead of taking the first matching method, we should find the best one
3799
nativeMethod = method;
3804
if (nativeMethod != null)
3809
ilGenerator.Emit(OpCodes.Ldarg_0);
3812
for (int j = 0; j < args.Length; j++)
3814
ilGenerator.EmitLdarg(j + add);
3816
ilGenerator.Emit(OpCodes.Call, nativeMethod);
3817
TypeWrapper retTypeWrapper = methods[i].ReturnType;
3818
if (!retTypeWrapper.TypeAsTBD.Equals(nativeMethod.ReturnType) && !retTypeWrapper.IsGhost)
3820
ilGenerator.Emit(OpCodes.Castclass, retTypeWrapper.TypeAsTBD);
3822
ilGenerator.Emit(OpCodes.Ret);
3826
if (wrapper.classLoader.NoJNI)
3828
// since NoJniStubs can only be set when we're statically compiling, it is safe to use the "compiler" trace switch
3829
Tracer.Warning(Tracer.Compiler, "Native method not implemented: {0}.{1}.{2}", classFile.Name, m.Name, m.Signature);
3830
ilGenerator.EmitThrow("java.lang.UnsatisfiedLinkError", "Native method not implemented (compiled with -nojni): " + classFile.Name + "." + m.Name + m.Signature);
3833
else if (StaticCompiler.runtimeJniAssembly == null)
3835
Console.Error.WriteLine("Error: Native method not implemented: {0}.{1}{2}", classFile.Name, m.Name, m.Signature);
3836
StaticCompiler.errorCount++;
3841
if (JVM.IsSaveDebugImage)
3843
#if !STATIC_COMPILER
3844
JniProxyBuilder.Generate(this, ilGenerator, wrapper, methods[i], typeBuilder, classFile, m, args);
3845
#endif // !STATIC_COMPILER
3849
JniBuilder.Generate(this, ilGenerator, wrapper, methods[i], typeBuilder, classFile, m, args, false);
3853
ilGenerator.DoEmit();
3857
Profiler.Leave("JavaTypeImpl.Finish.Native");
3862
CodeEmitter ilGenerator = CodeEmitter.Create(mb);
3863
TraceHelper.EmitMethodTrace(ilGenerator, classFile.Name + "." + m.Name + m.Signature);
3865
// do we have an implementation in map.xml?
3866
if (wrapper.EmitMapXmlMethodPrologueAndOrBody(ilGenerator, classFile, m))
3868
ilGenerator.DoEmit();
3871
#endif // STATIC_COMPILER
3872
bool nonleaf = false;
3873
Compiler.Compile(this, wrapper, methods[i], classFile, m, ilGenerator, ref nonleaf, invokespecialstubcache);
3874
ilGenerator.CheckLabels();
3875
ilGenerator.DoEmit();
3878
mb.SetImplementationFlags(mb.GetMethodImplementationFlags() | MethodImplAttributes.NoInlining);
3881
ilGenerator.EmitLineNumberTable((MethodBuilder)methods[i].GetMethod());
3882
#else // STATIC_COMPILER
3883
byte[] linenumbers = ilGenerator.GetLineNumberTable();
3884
if (linenumbers != null)
3886
if (wrapper.lineNumberTables == null)
3888
wrapper.lineNumberTables = new byte[methods.Length][];
3890
wrapper.lineNumberTables[i] = linenumbers;
3892
#endif // STATIC_COMPILER
3897
if (clinitIndex != -1 || (basehasclinit && !classFile.IsInterface) || classFile.HasInitializedFields)
3900
if (clinitIndex != -1)
3902
cb = (MethodBuilder)methods[clinitIndex].GetMethod();
3906
cb = ReflectUtil.DefineTypeInitializer(typeBuilder);
3907
AttributeHelper.HideFromJava(cb);
3909
CodeEmitter ilGenerator = CodeEmitter.Create(cb);
3910
// before we call the base class initializer, we need to set the non-final static ConstantValue fields
3911
EmitConstantValueInitialization(fields, ilGenerator);
3914
wrapper.BaseTypeWrapper.EmitRunClassConstructor(ilGenerator);
3916
if (clinitIndex != -1)
3918
CompileConstructorBody(this, ilGenerator, clinitIndex, invokespecialstubcache);
3922
ilGenerator.Emit(OpCodes.Ret);
3923
ilGenerator.DoEmit();
3925
ilGenerator.CheckLabels();
3928
// add all interfaces that we implement (including the magic ones) and handle ghost conversions
3929
ImplementInterfaces(wrapper.Interfaces, new List<TypeWrapper>());
3931
// NOTE non-final fields aren't allowed in interfaces so we don't have to initialize constant fields
3932
if (!classFile.IsInterface)
3934
// if a class has no constructor, we generate one otherwise Ref.Emit will create a default ctor
3935
// and that has several problems:
3936
// - base type may not have an accessible default constructor
3937
// - Ref.Emit uses BaseType.GetConstructors() which may trigger a TypeResolve event
3938
// - we don't want the synthesized constructor to show up in Java
3939
if (!hasConstructor)
3941
CodeEmitter ilgen = CodeEmitter.Create(ReflectUtil.DefineConstructor(typeBuilder, MethodAttributes.PrivateScope, Type.EmptyTypes));
3942
ilgen.Emit(OpCodes.Ldnull);
3943
ilgen.Emit(OpCodes.Throw);
3947
// here we loop thru all the interfaces to explicitly implement any methods that we inherit from
3948
// base types that may have a different name from the name in the interface
3949
// (e.g. interface that has an equals() method that should override System.Object.Equals())
3950
// also deals with interface methods that aren't implemented (generate a stub that throws AbstractMethodError)
3951
// and with methods that aren't public (generate a stub that throws IllegalAccessError)
3952
Dictionary<TypeWrapper, TypeWrapper> doneSet = new Dictionary<TypeWrapper, TypeWrapper>();
3953
TypeWrapper[] interfaces = wrapper.Interfaces;
3954
for (int i = 0; i < interfaces.Length; i++)
3956
ImplementInterfaceMethodStubs(doneSet, interfaces[i], false);
3958
// if any of our base classes has an incomplete interface implementation we need to look through all
3959
// the base class interfaces to see if we've got an implementation now
3960
TypeWrapper baseTypeWrapper = wrapper.BaseTypeWrapper;
3961
while (baseTypeWrapper.HasIncompleteInterfaceImplementation)
3963
for (int i = 0; i < baseTypeWrapper.Interfaces.Length; i++)
3965
ImplementInterfaceMethodStubs(doneSet, baseTypeWrapper.Interfaces[i], true);
3967
baseTypeWrapper = baseTypeWrapper.BaseTypeWrapper;
3969
if (!wrapper.IsAbstract && wrapper.HasUnsupportedAbstractMethods)
3971
AddUnsupportedAbstractMethods();
3973
if (!wrapper.GetClassLoader().NoAutomagicSerialization)
3975
wrapper.automagicSerializationCtor = Serialization.AddAutomagicSerialization(wrapper, typeBuilder);
3980
// If we're an interface that has public/protected fields, we create an inner class
3981
// to expose these fields to C# (which stubbornly refuses to see fields in interfaces).
3982
TypeBuilder tbFields = null;
3983
if (classFile.IsInterface && classFile.IsPublic && !wrapper.IsGhost && classFile.Fields.Length > 0)
3985
CompilerClassLoader ccl = wrapper.classLoader;
3986
string name = "__Fields";
3987
while (!ccl.ReserveName(classFile.Name + "$" + name))
3991
tbFields = typeBuilder.DefineNestedType(name, TypeAttributes.Class | TypeAttributes.NestedPublic | TypeAttributes.Sealed | TypeAttributes.Abstract);
3992
AttributeHelper.HideFromJava(tbFields);
3993
CodeEmitter ilgenClinit = null;
3994
for (int i = 0; i < classFile.Fields.Length; i++)
3996
ClassFile.Field f = classFile.Fields[i];
3997
if (f.ConstantValue != null)
3999
FieldAttributes attribs = FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.Literal;
4000
FieldBuilder fb = tbFields.DefineField(f.Name, fields[i].FieldTypeWrapper.TypeAsSignatureType, attribs);
4001
fb.SetConstant(f.ConstantValue);
4005
FieldAttributes attribs = FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.InitOnly;
4006
FieldBuilder fb = tbFields.DefineField(f.Name, ToPublicSignatureType(fields[i].FieldTypeWrapper), attribs);
4007
if (ilgenClinit == null)
4009
ilgenClinit = CodeEmitter.Create(ReflectUtil.DefineTypeInitializer(tbFields));
4011
wrapper.GetFieldWrapper(f.Name, f.Signature).EmitGet(ilgenClinit);
4012
ilgenClinit.Emit(OpCodes.Stsfld, fb);
4015
if (ilgenClinit != null)
4017
ilgenClinit.Emit(OpCodes.Ret);
4018
ilgenClinit.DoEmit();
4022
// See if there is any additional metadata
4023
wrapper.EmitMapXmlMetadata(typeBuilder, classFile, fields, methods);
4025
// if we inherit public members from non-public base classes or have public members with non-public types in their signature, we need access stubs
4026
if (wrapper.IsPublic)
4030
#endif // STATIC_COMPILER
4032
for (int i = 0; i < classFile.Methods.Length; i++)
4034
ClassFile.Method m = classFile.Methods[i];
4035
MethodBuilder mb = (MethodBuilder)methods[i].GetMethod();
4040
ParameterBuilder returnParameter = null;
4041
ParameterBuilder[] parameterBuilders = null;
4042
string[] parameterNames = null;
4043
if (wrapper.GetClassLoader().EmitDebugInfo
4045
|| (classFile.IsPublic && (m.IsPublic || m.IsProtected))
4049
parameterNames = new string[methods[i].GetParameters().Length];
4050
GetParameterNamesFromLVT(m, parameterNames);
4051
GetParameterNamesFromSig(m.Signature, parameterNames);
4053
wrapper.GetParameterNamesFromXml(m.Name, m.Signature, parameterNames);
4055
parameterBuilders = GetParameterBuilders(mb, parameterNames.Length, parameterNames);
4058
if ((m.Modifiers & Modifiers.VarArgs) != 0 && !methods[i].HasCallerID)
4060
if (parameterBuilders == null)
4062
parameterBuilders = GetParameterBuilders(mb, methods[i].GetParameters().Length, null);
4064
if (parameterBuilders.Length > 0)
4066
AttributeHelper.SetParamArrayAttribute(parameterBuilders[parameterBuilders.Length - 1]);
4069
wrapper.AddXmlMapParameterAttributes(mb, classFile.Name, m.Name, m.Signature, ref parameterBuilders);
4071
if (m.Annotations != null)
4073
foreach (object[] def in m.Annotations)
4075
Annotation annotation = Annotation.Load(wrapper.GetClassLoader(), def);
4076
if (annotation != null)
4078
annotation.Apply(wrapper.GetClassLoader(), mb, def);
4079
annotation.ApplyReturnValue(wrapper.GetClassLoader(), mb, ref returnParameter, def);
4083
if (m.ParameterAnnotations != null)
4085
if (parameterBuilders == null)
4087
parameterBuilders = GetParameterBuilders(mb, methods[i].GetParameters().Length, null);
4089
object[][] defs = m.ParameterAnnotations;
4090
for (int j = 0; j < defs.Length; j++)
4092
foreach (object[] def in defs[j])
4094
Annotation annotation = Annotation.Load(wrapper.GetClassLoader(), def);
4095
if (annotation != null)
4097
annotation.Apply(wrapper.GetClassLoader(), parameterBuilders[j], def);
4103
if (methods[i].HasCallerID)
4105
AttributeHelper.SetEditorBrowsableNever(mb);
4106
EmitCallerIDStub(methods[i], parameterNames);
4108
if (m.DllExportName != null && wrapper.classLoader.TryEnableUnmanagedExports())
4110
mb.__AddUnmanagedExport(m.DllExportName, m.DllExportOrdinal);
4112
#endif // STATIC_COMPILER
4115
for (int i = 0; i < classFile.Fields.Length; i++)
4117
if (classFile.Fields[i].Annotations != null)
4119
foreach (object[] def in classFile.Fields[i].Annotations)
4121
Annotation annotation = Annotation.Load(wrapper.GetClassLoader(), def);
4122
if (annotation != null)
4125
DynamicPropertyFieldWrapper prop = fields[i] as DynamicPropertyFieldWrapper;
4128
annotation.Apply(wrapper.GetClassLoader(), prop.GetPropertyBuilder(), def);
4132
annotation.Apply(wrapper.GetClassLoader(), (FieldBuilder)fields[i].GetField(), def);
4140
if (classFile.Annotations != null)
4142
foreach (object[] def in classFile.Annotations)
4144
Annotation annotation = Annotation.Load(wrapper.GetClassLoader(), def);
4145
if (annotation != null)
4147
annotation.Apply(wrapper.GetClassLoader(), typeBuilder, def);
4153
Profiler.Enter("TypeBuilder.CreateType");
4156
type = typeBuilder.CreateType();
4157
if (nestedTypeBuilders != null)
4159
ClassLoaderWrapper.LoadClassCritical("ikvm.internal.IntrinsicAtomicReferenceFieldUpdater").Finish();
4160
ClassLoaderWrapper.LoadClassCritical("ikvm.internal.IntrinsicThreadLocal").Finish();
4161
foreach (TypeBuilder tb in nestedTypeBuilders)
4167
if (tbFields != null)
4169
tbFields.CreateType();
4171
if (classFile.IsInterface && !classFile.IsPublic)
4173
((DynamicClassLoader)wrapper.classLoader.GetTypeWrapperFactory()).DefineProxyHelper(type);
4179
Profiler.Leave("TypeBuilder.CreateType");
4181
#if !STATIC_COMPILER
4182
// When we're statically compiling we don't need to set the wrapper here, because we've already done so for the typeBuilder earlier.
4183
wrapper.GetClassLoader().SetWrapperForType(type, wrapper);
4186
wrapper.FinishGhostStep2();
4188
BakedTypeCleanupHack.Process(wrapper);
4193
private void AddAccessStubs()
4196
* There are two types of access stubs:
4198
* Type 1 These are required when a public class extends a non-public class.
4199
* In that case we need access stubs for all public and protected members
4200
* of the non-public base classes.
4202
* Type 2 When a public class exposes a member that contains a non-public type in
4203
* its signature, we need an access stub for that member (where we convert
4204
* the non-public type in the signature to the first public base type).
4205
* Additionally, when a public or protected final field is compiled
4206
* without -strictfinalfieldsemantics, a the field will be wrapper with a
4207
* read-only property.
4209
* Note that type 1 access stubs may also need the type 2 signature type widening
4210
* if the signature contains non-public types.
4212
* Type 1 access stubs are always required, because the JVM allow access to these
4213
* members via the derived class while the CLR doesn't. Historically, we've exposed
4214
* these access stubs in such a way that they are also consumable from other .NET
4215
* languages (when feasible), so we'll continue to do that for back compat.
4217
* Type 2 access stubs are only required by the CLR when running on CLR v4 and the
4218
* caller assembly is security transparent code (level 2). We also want the access
4219
* stubs to allow other .NET languages (e.g. C#) to consume broken APIs that
4220
* (accidentally) expose these members.
4222
AddType2FieldAccessStubs();
4223
AddType1FieldAccessStubs(wrapper);
4224
if (!wrapper.IsInterface)
4227
AddType2MethodAccessStubs(ref id);
4228
AddType1MethodAccessStubs(ref id);
4232
private void AddType1FieldAccessStubs(TypeWrapper tw)
4238
foreach (FieldWrapper fw in tw.GetFields())
4240
if ((fw.IsPublic || (fw.IsProtected && !wrapper.IsFinal))
4241
&& wrapper.GetFieldWrapper(fw.Name, fw.Signature) == fw)
4243
GenerateAccessStub(fw, true);
4247
foreach (TypeWrapper iface in tw.Interfaces)
4249
AddType1FieldAccessStubs(iface);
4251
tw = tw.BaseTypeWrapper;
4252
} while (tw != null && !tw.IsPublic);
4255
private void AddType2FieldAccessStubs()
4257
foreach (FieldWrapper fw in wrapper.GetFields())
4259
if (wrapper.NeedsType2AccessStub(fw))
4261
GenerateAccessStub(fw, false);
4266
private void GenerateAccessStub(FieldWrapper fw, bool type1)
4268
if (fw is ConstantFieldWrapper)
4270
// constants cannot have a type 2 access stub, because constant types are always public
4271
Debug.Assert(type1);
4273
FieldAttributes attribs = fw.IsPublic ? FieldAttributes.Public : FieldAttributes.FamORAssem;
4274
attribs |= FieldAttributes.Static | FieldAttributes.Literal;
4275
// we attach the AccessStub custom modifier because the C# compiler prefers fields without custom modifiers
4276
// so if this class defines a field with the same name, that will be preferred over this one by the C# compiler
4277
FieldBuilder fb = typeBuilder.DefineField(fw.Name, fw.FieldTypeWrapper.TypeAsSignatureType, null, new Type[] { JVM.LoadType(typeof(IKVM.Attributes.AccessStub)) }, attribs);
4278
AttributeHelper.HideFromReflection(fb);
4279
fb.SetConstant(((ConstantFieldWrapper)fw).GetConstantValue());
4283
Type propType = ToPublicSignatureType(fw.FieldTypeWrapper);
4284
Type[] modopt = wrapper.GetModOpt(fw.FieldTypeWrapper, true);
4285
PropertyBuilder pb = typeBuilder.DefineProperty(fw.Name, PropertyAttributes.None, propType, null, modopt, Type.EmptyTypes, null, null);
4288
AttributeHelper.HideFromReflection(pb);
4292
AttributeHelper.SetModifiers(pb, fw.Modifiers, fw.IsInternal);
4294
MethodAttributes attribs = fw.IsPublic ? MethodAttributes.Public : MethodAttributes.FamORAssem;
4295
attribs |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
4298
attribs |= MethodAttributes.Static;
4300
// we append the IKVM.Attributes.AccessStub type to the modopt array for use in the property accessor method signature
4301
// to make sure they never conflict with any user defined methhods
4302
Type[] modopt2 = modopt;
4303
Array.Resize(ref modopt2, modopt2.Length + 1);
4304
modopt2[modopt2.Length - 1] = JVM.LoadType(typeof(IKVM.Attributes.AccessStub));
4305
MethodBuilder getter = typeBuilder.DefineMethod("get_" + fw.Name, attribs, CallingConventions.Standard, propType, null, modopt2, Type.EmptyTypes, null, null);
4306
AttributeHelper.HideFromJava(getter);
4307
pb.SetGetMethod(getter);
4308
CodeEmitter ilgen = CodeEmitter.Create(getter);
4311
ilgen.Emit(OpCodes.Ldarg_0);
4314
ilgen.Emit(OpCodes.Ret);
4316
if (!fw.IsFinal || (!fw.IsStatic && !type1))
4320
// we need to generate a (private) setter for final fields for reflection and serialization
4321
attribs &= ~MethodAttributes.MemberAccessMask;
4322
attribs |= MethodAttributes.Private;
4324
MethodBuilder setter = typeBuilder.DefineMethod("set_" + fw.Name, attribs, CallingConventions.Standard, null, null, null, new Type[] { propType }, null, new Type[][] { modopt2 });
4325
AttributeHelper.HideFromJava(setter);
4326
pb.SetSetMethod(setter);
4327
ilgen = CodeEmitter.Create(setter);
4328
ilgen.Emit(OpCodes.Ldarg_0);
4331
ilgen.Emit(OpCodes.Ldarg_1);
4333
// we don't do a DynamicCast if fw.FieldTypeWrapper is unloadable, because for normal unloadable fields we don't enfore the type either
4334
if (propType != fw.FieldTypeWrapper.TypeAsSignatureType)
4336
ilgen.Emit(OpCodes.Castclass, fw.FieldTypeWrapper.TypeAsSignatureType);
4339
ilgen.Emit(OpCodes.Ret);
4345
private void AddType1MethodAccessStubs(ref int id)
4347
for (TypeWrapper tw = wrapper.BaseTypeWrapper; tw != null && !tw.IsPublic; tw = tw.BaseTypeWrapper)
4349
foreach (MethodWrapper mw in tw.GetMethods())
4351
if ((mw.IsPublic || (mw.IsProtected && !wrapper.IsFinal))
4352
&& (!mw.IsAbstract || wrapper.IsAbstract)
4353
&& mw.Name != StringConstants.INIT
4354
&& wrapper.GetMethodWrapper(mw.Name, mw.Signature, true) == mw
4355
&& ParametersAreAccessible(mw))
4357
GenerateAccessStub(id, mw, true, true);
4358
if (!mw.IsStatic && !mw.IsFinal && !mw.IsAbstract && !wrapper.IsFinal)
4360
GenerateAccessStub(id, mw, false, true);
4368
private void AddType2MethodAccessStubs(ref int id)
4370
foreach (MethodWrapper mw in wrapper.GetMethods())
4372
if (mw.HasNonPublicTypeInSignature
4373
&& (mw.IsPublic || (mw.IsProtected && !wrapper.IsFinal))
4374
&& ParametersAreAccessible(mw))
4376
GenerateAccessStub(id, mw, true, false);
4377
if (!mw.IsStatic && !mw.IsFinal && !mw.IsAbstract && mw.Name != StringConstants.INIT && !wrapper.IsFinal)
4379
GenerateAccessStub(id, mw, false, false);
4386
private void GenerateAccessStub(int id, MethodWrapper mw, bool virt, bool type1)
4388
Debug.Assert(!mw.HasCallerID);
4389
MethodAttributes stubattribs = mw.IsPublic && virt ? MethodAttributes.Public : MethodAttributes.FamORAssem;
4390
stubattribs |= MethodAttributes.HideBySig;
4393
stubattribs |= MethodAttributes.Static;
4395
TypeWrapper[] parameters = mw.GetParameters();
4396
Type[] realParameterTypes = new Type[parameters.Length];
4397
Type[] parameterTypes = new Type[parameters.Length];
4398
Type[][] modopt = new Type[parameters.Length][];
4399
for (int i = 0; i < parameters.Length; i++)
4401
realParameterTypes[i] = parameters[i].TypeAsSignatureType;
4402
parameterTypes[i] = ToPublicSignatureType(parameters[i]);
4403
modopt[i] = wrapper.GetModOpt(parameters[i], true);
4405
Type returnType = ToPublicSignatureType(mw.ReturnType);
4406
Type[] modoptReturnType = wrapper.GetModOpt(mw.ReturnType, true);
4407
Array.Resize(ref modoptReturnType, modoptReturnType.Length + 1);
4408
modoptReturnType[modoptReturnType.Length - 1] = JVM.LoadType(typeof(IKVM.Attributes.AccessStub));
4410
if (mw.Name == StringConstants.INIT)
4412
name = ConstructorInfo.ConstructorName;
4413
stubattribs |= MethodAttributes.SpecialName | MethodAttributes.RTSpecialName;
4418
? (mw.Modifiers & Modifiers.Bridge) == 0 ? mw.Name : NamePrefix.Bridge + mw.Name
4419
: NamePrefix.NonVirtual + id;
4421
MethodBuilder mb = typeBuilder.DefineMethod(name, stubattribs, CallingConventions.Standard, returnType, null, modoptReturnType, parameterTypes, null, modopt);
4424
AttributeHelper.HideFromReflection(mb);
4425
AttributeHelper.SetNameSig(mb, NamePrefix.AccessStub + id + "|" + mw.Name, mw.Signature);
4429
AttributeHelper.HideFromJava(mb);
4432
AttributeHelper.SetNameSig(mb, mw.Name, mw.Signature);
4435
CodeEmitter ilgen = CodeEmitter.Create(mb);
4439
ilgen.EmitLdarg(argpos++);
4441
for (int i = 0; i < parameterTypes.Length; i++)
4443
ilgen.EmitLdarg(argpos++);
4444
// we don't need to do a DynamicCast if for unloadables, because the method itself will already do that
4445
if (parameterTypes[i] != realParameterTypes[i])
4447
ilgen.Emit(OpCodes.Castclass, realParameterTypes[i]);
4450
if (mw.IsStatic || !virt || mw.Name == StringConstants.INIT)
4456
mw.EmitCallvirt(ilgen);
4458
ilgen.Emit(OpCodes.Ret);
4462
private static Type ToPublicSignatureType(TypeWrapper tw)
4464
return (tw.IsPublic ? tw : tw.GetPublicBaseTypeWrapper()).TypeAsSignatureType;
4467
private bool ParametersAreAccessible(MethodWrapper mw)
4469
foreach (TypeWrapper tw in mw.GetParameters())
4471
if (!tw.IsAccessibleFrom(wrapper))
4478
#endif // STATIC_COMPILER
4480
private void ImplementInterfaceMethodStubs(Dictionary<TypeWrapper, TypeWrapper> doneSet, TypeWrapper interfaceTypeWrapper, bool baseClassInterface)
4482
Debug.Assert(interfaceTypeWrapper.IsInterface);
4484
// make sure we don't do the same method twice
4485
if (doneSet.ContainsKey(interfaceTypeWrapper))
4489
doneSet.Add(interfaceTypeWrapper, interfaceTypeWrapper);
4490
foreach (MethodWrapper method in interfaceTypeWrapper.GetMethods())
4492
if (!method.IsStatic && !method.IsDynamicOnly)
4494
ImplementInterfaceMethodStubImpl(method, baseClassInterface);
4497
TypeWrapper[] interfaces = interfaceTypeWrapper.Interfaces;
4498
for (int i = 0; i < interfaces.Length; i++)
4500
ImplementInterfaceMethodStubs(doneSet, interfaces[i], baseClassInterface);
4504
private void ImplementInterfaceMethodStubImpl(MethodWrapper ifmethod, bool baseClassInterface)
4506
// we're mangling the name to prevent subclasses from accidentally overriding this method and to
4507
// prevent clashes with overloaded method stubs that are erased to the same signature (e.g. unloadable types and ghost arrays)
4508
// HACK the signature and name are the wrong way around to work around a C++/CLI bug (apparantely it looks looks at the last n
4509
// characters of the method name, or something bizarre like that)
4510
// https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=234167
4511
string mangledName = ifmethod.DeclaringType.Name + "/" + ifmethod.Signature + ifmethod.Name;
4512
MethodWrapper mce = null;
4513
TypeWrapper lookup = wrapper;
4514
while (lookup != null)
4516
mce = lookup.GetMethodWrapper(ifmethod.Name, ifmethod.Signature, true);
4517
if (mce == null || !mce.IsStatic)
4521
lookup = mce.DeclaringType.BaseTypeWrapper;
4525
Debug.Assert(!mce.HasCallerID);
4526
if (mce.DeclaringType != wrapper)
4528
// check the loader constraints
4530
if (mce.ReturnType != ifmethod.ReturnType)
4532
// TODO handle unloadable
4535
TypeWrapper[] mceparams = mce.GetParameters();
4536
TypeWrapper[] ifparams = ifmethod.GetParameters();
4537
for (int i = 0; i < mceparams.Length; i++)
4539
if (mceparams[i] != ifparams[i])
4541
// TODO handle unloadable
4548
MethodBuilder mb = DefineInterfaceStubMethod(mangledName, ifmethod);
4549
AttributeHelper.HideFromJava(mb);
4550
CodeEmitter ilgen = CodeEmitter.Create(mb);
4551
ilgen.EmitThrow("java.lang.LinkageError", wrapper.Name + "." + ifmethod.Name + ifmethod.Signature);
4553
typeBuilder.DefineMethodOverride(mb, (MethodInfo)ifmethod.GetMethod());
4557
if (mce.IsMirandaMethod && mce.DeclaringType == wrapper)
4559
// Miranda methods already have a methodimpl (if needed) to implement the correct interface method
4561
else if (!mce.IsPublic && !mce.IsInternal)
4563
// NOTE according to the ECMA spec it isn't legal for a privatescope method to be virtual, but this works and
4564
// it makes sense, so I hope the spec is wrong
4565
// UPDATE unfortunately, according to Serge Lidin the spec is correct, and it is not allowed to have virtual privatescope
4566
// methods. Sigh! So I have to use private methods and mangle the name
4567
MethodBuilder mb = DefineInterfaceStubMethod(mangledName, ifmethod);
4568
AttributeHelper.HideFromJava(mb);
4569
CodeEmitter ilgen = CodeEmitter.Create(mb);
4570
ilgen.EmitThrow("java.lang.IllegalAccessError", wrapper.Name + "." + ifmethod.Name + ifmethod.Signature);
4572
typeBuilder.DefineMethodOverride(mb, (MethodInfo)ifmethod.GetMethod());
4573
wrapper.HasIncompleteInterfaceImplementation = true;
4575
else if (mce.GetMethod() == null || mce.RealName != ifmethod.RealName || mce.IsInternal)
4577
MethodBuilder mb = DefineInterfaceStubMethod(mangledName, ifmethod);
4578
AttributeHelper.HideFromJava(mb);
4579
CodeEmitter ilGenerator = CodeEmitter.Create(mb);
4580
ilGenerator.Emit(OpCodes.Ldarg_0);
4581
int argc = mce.GetParameters().Length;
4582
for (int n = 0; n < argc; n++)
4584
ilGenerator.EmitLdarg(n + 1);
4586
mce.EmitCallvirt(ilGenerator);
4587
ilGenerator.Emit(OpCodes.Ret);
4588
ilGenerator.DoEmit();
4589
typeBuilder.DefineMethodOverride(mb, (MethodInfo)ifmethod.GetMethod());
4591
else if (!ReflectUtil.IsSameAssembly(mce.DeclaringType.TypeAsTBD, typeBuilder))
4593
// NOTE methods inherited from base classes in a different assembly do *not* automatically implement
4594
// interface methods, so we have to generate a stub here that doesn't do anything but call the base
4596
MethodBuilder mb = DefineInterfaceStubMethod(mangledName, ifmethod);
4597
typeBuilder.DefineMethodOverride(mb, (MethodInfo)ifmethod.GetMethod());
4598
AttributeHelper.HideFromJava(mb);
4599
CodeEmitter ilGenerator = CodeEmitter.Create(mb);
4600
ilGenerator.Emit(OpCodes.Ldarg_0);
4601
int argc = mce.GetParameters().Length;
4602
for (int n = 0; n < argc; n++)
4604
ilGenerator.EmitLdarg(n + 1);
4606
mce.EmitCallvirt(ilGenerator);
4607
ilGenerator.Emit(OpCodes.Ret);
4608
ilGenerator.DoEmit();
4610
else if (CheckRequireOverrideStub(mce, ifmethod))
4612
wrapper.GenerateOverrideStub(typeBuilder, ifmethod, (MethodInfo)mce.GetMethod(), mce);
4614
else if (baseClassInterface && mce.DeclaringType == wrapper)
4616
typeBuilder.DefineMethodOverride((MethodInfo)mce.GetMethod(), (MethodInfo)ifmethod.GetMethod());
4621
if (!wrapper.IsAbstract || (!baseClassInterface && wrapper.GetMethodWrapper(ifmethod.Name, ifmethod.Signature, false) != null))
4623
// the type doesn't implement the interface method and isn't abstract either. The JVM allows this, but the CLR doesn't,
4624
// so we have to create a stub method that throws an AbstractMethodError
4625
MethodBuilder mb = DefineInterfaceStubMethod(mangledName, ifmethod);
4626
AttributeHelper.HideFromJava(mb);
4627
CodeEmitter ilgen = CodeEmitter.Create(mb);
4628
ilgen.EmitThrow("java.lang.AbstractMethodError", wrapper.Name + "." + ifmethod.Name + ifmethod.Signature);
4630
typeBuilder.DefineMethodOverride(mb, (MethodInfo)ifmethod.GetMethod());
4631
wrapper.HasIncompleteInterfaceImplementation = true;
4636
private MethodBuilder DefineInterfaceStubMethod(string name, MethodWrapper mw)
4638
return mw.GetDefineMethodHelper().DefineMethod(wrapper, typeBuilder, name, MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Private | MethodAttributes.Virtual | MethodAttributes.Final);
4641
private static class BakedTypeCleanupHack
4643
#if NET_4_0 || STATIC_COMPILER
4644
internal static void Process(DynamicTypeWrapper wrapper) { }
4646
private static readonly FieldInfo m_methodBuilder = typeof(ConstructorBuilder).GetField("m_methodBuilder", BindingFlags.Instance | BindingFlags.NonPublic);
4647
private static readonly FieldInfo[] methodBuilderFields = GetFieldList(typeof(MethodBuilder), new string[]
4661
private static readonly FieldInfo[] fieldBuilderFields = GetFieldList(typeof(FieldBuilder), new string[]
4667
private static bool IsSupportedVersion
4671
return Environment.Version.Major == 2 && Environment.Version.Minor == 0 && Environment.Version.Build == 50727 && Environment.Version.Revision == 4016;
4676
[SecurityTreatAsSafe]
4677
private static FieldInfo[] GetFieldList(Type type, string[] list)
4679
if (JVM.SafeGetEnvironmentVariable("IKVM_DISABLE_TYPEBUILDER_HACK") != null || !IsSupportedVersion)
4683
if (!SecurityManager.IsGranted(new SecurityPermission(SecurityPermissionFlag.Assertion)) ||
4684
!SecurityManager.IsGranted(new ReflectionPermission(ReflectionPermissionFlag.MemberAccess)))
4688
FieldInfo[] fields = new FieldInfo[list.Length];
4689
for (int i = 0; i < list.Length; i++)
4691
fields[i] = type.GetField(list[i], BindingFlags.Instance | BindingFlags.NonPublic);
4692
if (fields[i] == null)
4701
[SecurityTreatAsSafe]
4702
internal static void Process(DynamicTypeWrapper wrapper)
4704
if (m_methodBuilder != null && methodBuilderFields != null && fieldBuilderFields != null)
4706
foreach (MethodWrapper mw in wrapper.GetMethods())
4708
MethodBuilder mb = mw.GetMethod() as MethodBuilder;
4711
ConstructorBuilder cb = mw.GetMethod() as ConstructorBuilder;
4714
new ReflectionPermission(ReflectionPermissionFlag.MemberAccess).Assert();
4715
mb = (MethodBuilder)m_methodBuilder.GetValue(cb);
4716
CodeAccessPermission.RevertAssert();
4721
new ReflectionPermission(ReflectionPermissionFlag.MemberAccess).Assert();
4722
foreach (FieldInfo fi in methodBuilderFields)
4724
fi.SetValue(mb, null);
4726
CodeAccessPermission.RevertAssert();
4729
foreach (FieldWrapper fw in wrapper.GetFields())
4731
FieldBuilder fb = fw.GetField() as FieldBuilder;
4734
new ReflectionPermission(ReflectionPermissionFlag.MemberAccess).Assert();
4735
foreach (FieldInfo fi in fieldBuilderFields)
4737
fi.SetValue(fb, null);
4739
CodeAccessPermission.RevertAssert();
4747
#if !STATIC_COMPILER
4748
internal static class JniProxyBuilder
4750
private static ModuleBuilder mod;
4751
private static int count;
4753
static JniProxyBuilder()
4755
AssemblyName name = new AssemblyName();
4756
name.Name = "jniproxy";
4757
AssemblyBuilder ab = AppDomain.CurrentDomain.DefineDynamicAssembly(name, JVM.IsSaveDebugImage ? AssemblyBuilderAccess.RunAndSave : AssemblyBuilderAccess.Run);
4758
DynamicClassLoader.RegisterForSaveDebug(ab);
4759
mod = ab.DefineDynamicModule("jniproxy.dll", "jniproxy.dll");
4760
CustomAttributeBuilder cab = new CustomAttributeBuilder(JVM.LoadType(typeof(JavaModuleAttribute)).GetConstructor(Type.EmptyTypes), new object[0]);
4761
mod.SetCustomAttribute(cab);
4764
internal static void Generate(DynamicTypeWrapper.FinishContext context, CodeEmitter ilGenerator, DynamicTypeWrapper wrapper, MethodWrapper mw, TypeBuilder typeBuilder, ClassFile classFile, ClassFile.Method m, TypeWrapper[] args)
4766
TypeBuilder tb = mod.DefineType("__<jni>" + (count++), TypeAttributes.Public | TypeAttributes.Class);
4767
int instance = m.IsStatic ? 0 : 1;
4768
Type[] argTypes = new Type[args.Length + instance + 1];
4771
argTypes[0] = typeof(object);
4773
for (int i = 0; i < args.Length; i++)
4775
// NOTE we take a shortcut here by assuming that all "special" types (i.e. ghost or value types)
4776
// are public and so we can get away with replacing all other types with object.
4777
argTypes[i + instance] = (args[i].IsPrimitive || args[i].IsGhost || args[i].IsNonPrimitiveValueType) ? args[i].TypeAsSignatureType : typeof(object);
4779
argTypes[argTypes.Length - 1] = ClassLoaderWrapper.LoadClassCritical("ikvm.internal.CallerID").TypeAsSignatureType;
4780
Type retType = (mw.ReturnType.IsPrimitive || mw.ReturnType.IsGhost || mw.ReturnType.IsNonPrimitiveValueType) ? mw.ReturnType.TypeAsSignatureType : typeof(object);
4781
MethodBuilder mb = tb.DefineMethod("method", MethodAttributes.Public | MethodAttributes.Static, retType, argTypes);
4782
AttributeHelper.HideFromJava(mb);
4783
CodeEmitter ilgen = CodeEmitter.Create(mb);
4784
JniBuilder.Generate(context, ilgen, wrapper, mw, tb, classFile, m, args, true);
4787
for (int i = 0; i < argTypes.Length - 1; i++)
4789
ilGenerator.EmitLdarg(i);
4791
context.EmitCallerID(ilGenerator);
4792
ilGenerator.Emit(OpCodes.Call, mb);
4793
if (!mw.ReturnType.IsPrimitive && !mw.ReturnType.IsGhost && !mw.ReturnType.IsNonPrimitiveValueType)
4795
ilGenerator.Emit(OpCodes.Castclass, mw.ReturnType.TypeAsSignatureType);
4797
ilGenerator.Emit(OpCodes.Ret);
4800
#endif // !STATIC_COMPILER
4802
private static class JniBuilder
4805
private static readonly Type localRefStructType = StaticCompiler.GetRuntimeType("IKVM.Runtime.JNI+Frame");
4807
private static readonly Type localRefStructType = null;
4809
private static readonly Type localRefStructType = JVM.LoadType(typeof(IKVM.Runtime.JNI.Frame));
4811
private static readonly MethodInfo jniFuncPtrMethod = localRefStructType.GetMethod("GetFuncPtr");
4812
private static readonly MethodInfo enterLocalRefStruct = localRefStructType.GetMethod("Enter");
4813
private static readonly MethodInfo leaveLocalRefStruct = localRefStructType.GetMethod("Leave");
4814
private static readonly MethodInfo makeLocalRef = localRefStructType.GetMethod("MakeLocalRef");
4815
private static readonly MethodInfo unwrapLocalRef = localRefStructType.GetMethod("UnwrapLocalRef");
4816
private static readonly MethodInfo writeLine = JVM.Import(typeof(Console)).GetMethod("WriteLine", new Type[] { Types.Object });
4817
private static readonly MethodInfo monitorEnter = JVM.Import(typeof(System.Threading.Monitor)).GetMethod("Enter", new Type[] { Types.Object });
4818
private static readonly MethodInfo monitorExit = JVM.Import(typeof(System.Threading.Monitor)).GetMethod("Exit", new Type[] { Types.Object });
4820
internal static void Generate(DynamicTypeWrapper.FinishContext context, CodeEmitter ilGenerator, DynamicTypeWrapper wrapper, MethodWrapper mw, TypeBuilder typeBuilder, ClassFile classFile, ClassFile.Method m, TypeWrapper[] args, bool thruProxy)
4822
CodeEmitterLocal syncObject = null;
4823
if (m.IsSynchronized && m.IsStatic)
4825
wrapper.EmitClassLiteral(ilGenerator);
4826
ilGenerator.Emit(OpCodes.Dup);
4827
syncObject = ilGenerator.DeclareLocal(Types.Object);
4828
ilGenerator.Emit(OpCodes.Stloc, syncObject);
4829
ilGenerator.Emit(OpCodes.Call, monitorEnter);
4830
ilGenerator.BeginExceptionBlock();
4832
string sig = m.Signature.Replace('.', '/');
4833
// TODO use/unify JNI.METHOD_PTR_FIELD_PREFIX
4834
FieldBuilder methodPtr = typeBuilder.DefineField("__<jniptr>" + m.Name + sig, Types.IntPtr, FieldAttributes.Static | FieldAttributes.PrivateScope);
4835
CodeEmitterLocal localRefStruct = ilGenerator.DeclareLocal(localRefStructType);
4836
ilGenerator.Emit(OpCodes.Ldloca, localRefStruct);
4837
ilGenerator.Emit(OpCodes.Initobj, localRefStructType);
4838
ilGenerator.Emit(OpCodes.Ldsfld, methodPtr);
4839
CodeEmitterLabel oklabel = ilGenerator.DefineLabel();
4840
ilGenerator.EmitBrtrue(oklabel);
4843
ilGenerator.EmitLdarg(args.Length + (mw.IsStatic ? 0 : 1));
4847
context.EmitCallerID(ilGenerator);
4849
ilGenerator.Emit(OpCodes.Ldstr, classFile.Name.Replace('.', '/'));
4850
ilGenerator.Emit(OpCodes.Ldstr, m.Name);
4851
ilGenerator.Emit(OpCodes.Ldstr, sig);
4852
ilGenerator.Emit(OpCodes.Call, jniFuncPtrMethod);
4853
ilGenerator.Emit(OpCodes.Stsfld, methodPtr);
4854
ilGenerator.MarkLabel(oklabel);
4855
ilGenerator.Emit(OpCodes.Ldloca, localRefStruct);
4858
ilGenerator.EmitLdarg(args.Length + (mw.IsStatic ? 0 : 1));
4862
context.EmitCallerID(ilGenerator);
4864
ilGenerator.Emit(OpCodes.Call, enterLocalRefStruct);
4865
CodeEmitterLocal jnienv = ilGenerator.DeclareLocal(Types.IntPtr);
4866
ilGenerator.Emit(OpCodes.Stloc, jnienv);
4867
ilGenerator.BeginExceptionBlock();
4868
TypeWrapper retTypeWrapper = mw.ReturnType;
4869
if (!retTypeWrapper.IsUnloadable && !retTypeWrapper.IsPrimitive)
4871
// this one is for use after we return from "calli"
4872
ilGenerator.Emit(OpCodes.Ldloca, localRefStruct);
4874
ilGenerator.Emit(OpCodes.Ldloc, jnienv);
4875
Type[] modargs = new Type[args.Length + 2];
4876
modargs[0] = Types.IntPtr;
4877
modargs[1] = Types.IntPtr;
4878
for (int i = 0; i < args.Length; i++)
4880
modargs[i + 2] = args[i].TypeAsSignatureType;
4885
ilGenerator.Emit(OpCodes.Ldloca, localRefStruct);
4886
ilGenerator.Emit(OpCodes.Ldarg_0);
4887
ilGenerator.Emit(OpCodes.Call, makeLocalRef);
4892
ilGenerator.Emit(OpCodes.Ldloca, localRefStruct);
4893
wrapper.EmitClassLiteral(ilGenerator);
4894
ilGenerator.Emit(OpCodes.Call, makeLocalRef);
4896
for (int j = 0; j < args.Length; j++)
4898
if (args[j].IsUnloadable || !args[j].IsPrimitive)
4900
ilGenerator.Emit(OpCodes.Ldloca, localRefStruct);
4901
if (!args[j].IsUnloadable && args[j].IsNonPrimitiveValueType)
4903
ilGenerator.EmitLdarg(j + add);
4904
args[j].EmitBox(ilGenerator);
4906
else if (!args[j].IsUnloadable && args[j].IsGhost)
4908
ilGenerator.EmitLdarga(j + add);
4909
ilGenerator.Emit(OpCodes.Ldfld, args[j].GhostRefField);
4913
ilGenerator.EmitLdarg(j + add);
4915
ilGenerator.Emit(OpCodes.Call, makeLocalRef);
4916
modargs[j + 2] = Types.IntPtr;
4920
ilGenerator.EmitLdarg(j + add);
4923
ilGenerator.Emit(OpCodes.Ldsfld, methodPtr);
4925
if (retTypeWrapper == PrimitiveTypeWrapper.BOOLEAN)
4927
realRetType = Types.Byte;
4929
else if (retTypeWrapper.IsPrimitive)
4931
realRetType = retTypeWrapper.TypeAsSignatureType;
4935
realRetType = Types.IntPtr;
4937
ilGenerator.EmitCalli(OpCodes.Calli, System.Runtime.InteropServices.CallingConvention.StdCall, realRetType, modargs);
4938
CodeEmitterLocal retValue = null;
4939
if (retTypeWrapper != PrimitiveTypeWrapper.VOID)
4941
if (!retTypeWrapper.IsUnloadable && !retTypeWrapper.IsPrimitive)
4943
ilGenerator.Emit(OpCodes.Call, unwrapLocalRef);
4944
if (retTypeWrapper.IsNonPrimitiveValueType)
4946
retTypeWrapper.EmitUnbox(ilGenerator);
4948
else if (retTypeWrapper.IsGhost)
4950
CodeEmitterLocal ghost = ilGenerator.DeclareLocal(retTypeWrapper.TypeAsSignatureType);
4951
CodeEmitterLocal obj = ilGenerator.DeclareLocal(Types.Object);
4952
ilGenerator.Emit(OpCodes.Stloc, obj);
4953
ilGenerator.Emit(OpCodes.Ldloca, ghost);
4954
ilGenerator.Emit(OpCodes.Ldloc, obj);
4955
ilGenerator.Emit(OpCodes.Stfld, retTypeWrapper.GhostRefField);
4956
ilGenerator.Emit(OpCodes.Ldloc, ghost);
4960
ilGenerator.Emit(OpCodes.Castclass, retTypeWrapper.TypeAsTBD);
4963
retValue = ilGenerator.DeclareLocal(retTypeWrapper.TypeAsSignatureType);
4964
ilGenerator.Emit(OpCodes.Stloc, retValue);
4966
CodeEmitterLabel retLabel = ilGenerator.DefineLabel();
4967
ilGenerator.EmitLeave(retLabel);
4968
ilGenerator.BeginCatchBlock(Types.Object);
4969
ilGenerator.Emit(OpCodes.Ldstr, "*** exception in native code ***");
4970
ilGenerator.Emit(OpCodes.Call, writeLine);
4971
ilGenerator.Emit(OpCodes.Call, writeLine);
4972
ilGenerator.Emit(OpCodes.Rethrow);
4973
ilGenerator.BeginFinallyBlock();
4974
ilGenerator.Emit(OpCodes.Ldloca, localRefStruct);
4975
ilGenerator.Emit(OpCodes.Call, leaveLocalRefStruct);
4976
ilGenerator.Emit(OpCodes.Endfinally);
4977
ilGenerator.EndExceptionBlock();
4978
if (m.IsSynchronized && m.IsStatic)
4980
ilGenerator.BeginFinallyBlock();
4981
ilGenerator.Emit(OpCodes.Ldloc, syncObject);
4982
ilGenerator.Emit(OpCodes.Call, monitorExit);
4983
ilGenerator.Emit(OpCodes.Endfinally);
4984
ilGenerator.EndExceptionBlock();
4986
ilGenerator.MarkLabel(retLabel);
4987
if (retTypeWrapper != PrimitiveTypeWrapper.VOID)
4989
ilGenerator.Emit(OpCodes.Ldloc, retValue);
4991
ilGenerator.Emit(OpCodes.Ret);
4995
private static class TraceHelper
4998
private readonly static MethodInfo methodIsTracedMethod = JVM.LoadType(typeof(Tracer)).GetMethod("IsTracedMethod");
5000
private readonly static MethodInfo methodMethodInfo = JVM.LoadType(typeof(Tracer)).GetMethod("MethodInfo");
5002
internal static void EmitMethodTrace(CodeEmitter ilgen, string tracemessage)
5004
if (Tracer.IsTracedMethod(tracemessage))
5006
CodeEmitterLabel label = ilgen.DefineLabel();
5008
// TODO this should be a boolean field test instead of a call to Tracer.IsTracedMessage
5009
ilgen.Emit(OpCodes.Ldstr, tracemessage);
5010
ilgen.Emit(OpCodes.Call, methodIsTracedMethod);
5011
ilgen.EmitBrfalse(label);
5013
ilgen.Emit(OpCodes.Ldstr, tracemessage);
5014
ilgen.Emit(OpCodes.Call, methodMethodInfo);
5015
ilgen.MarkLabel(label);
5021
private void EmitCallerIDStub(MethodWrapper mw, string[] parameterNames)
5023
// we don't need to support custom modifiers, because there aren't any callerid methods that have parameter types that require a custom modifier
5024
TypeWrapper[] parameters = mw.GetParameters();
5025
Type[] parameterTypes = new Type[parameters.Length];
5026
for (int i = 0; i < parameterTypes.Length; i++)
5028
parameterTypes[i] = parameters[i].TypeAsSignatureType;
5030
MethodAttributes attribs = MethodAttributes.HideBySig;
5031
int argcount = parameterTypes.Length;
5034
attribs |= MethodAttributes.Static;
5042
attribs |= MethodAttributes.Public;
5044
else if (mw.IsProtected)
5046
attribs |= MethodAttributes.FamORAssem;
5048
else if (mw.IsPrivate)
5050
attribs |= MethodAttributes.Private;
5054
attribs |= MethodAttributes.Assembly;
5056
MethodBuilder mb = typeBuilder.DefineMethod(mw.Name, attribs, mw.ReturnType.TypeAsSignatureType, parameterTypes);
5057
AttributeHelper.HideFromJava(mb);
5058
mb.SetImplementationFlags(MethodImplAttributes.NoInlining);
5059
CodeEmitter ilgen = CodeEmitter.Create(mb);
5060
for (int i = 0; i < argcount; i++)
5062
if (parameterNames != null && (mw.IsStatic || i > 0))
5064
ParameterBuilder pb = mb.DefineParameter(mw.IsStatic ? i + 1 : i, ParameterAttributes.None, parameterNames[mw.IsStatic ? i : i - 1]);
5065
if (i == argcount - 1 && (mw.Modifiers & Modifiers.VarArgs) != 0)
5067
AttributeHelper.SetParamArrayAttribute(pb);
5072
ilgen.Emit(OpCodes.Ldc_I4_1);
5073
ilgen.Emit(OpCodes.Ldc_I4_0);
5074
ilgen.Emit(OpCodes.Newobj, JVM.Import(typeof(StackFrame)).GetConstructor(new Type[] { Types.Int32, Types.Boolean }));
5075
MethodWrapper callerID = CoreClasses.ikvm.@internal.CallerID.Wrapper.GetMethodWrapper("create", "(Lcli.System.Diagnostics.StackFrame;)Likvm.internal.CallerID;", false);
5077
callerID.EmitCall(ilgen);
5084
mw.EmitCallvirt(ilgen);
5086
ilgen.Emit(OpCodes.Ret);
5089
#endif // STATIC_COMPILER
5091
private void ImplementInterfaces(TypeWrapper[] interfaces, List<TypeWrapper> interfaceList)
5093
foreach (TypeWrapper iface in interfaces)
5095
if (!interfaceList.Contains(iface))
5097
interfaceList.Add(iface);
5098
// NOTE we're using TypeAsBaseType for the interfaces!
5099
Type ifaceType = iface.TypeAsBaseType;
5100
if (!iface.IsPublic && !ReflectUtil.IsSameAssembly(ifaceType, typeBuilder))
5102
ifaceType = ReflectUtil.GetAssembly(ifaceType).GetType(DynamicClassLoader.GetProxyHelperName(ifaceType));
5104
typeBuilder.AddInterfaceImplementation(ifaceType);
5106
if (!wrapper.IsInterface)
5108
// look for "magic" interfaces that imply a .NET interface
5109
if (iface.GetClassLoader() == CoreClasses.java.lang.Object.Wrapper.GetClassLoader())
5111
if (iface.Name == "java.lang.Iterable"
5112
&& !wrapper.ImplementsInterface(ClassLoaderWrapper.GetWrapperFromType(JVM.Import(typeof(System.Collections.IEnumerable)))))
5114
TypeWrapper enumeratorType = ClassLoaderWrapper.GetBootstrapClassLoader().LoadClassByDottedNameFast("ikvm.lang.IterableEnumerator");
5115
if (enumeratorType != null)
5117
typeBuilder.AddInterfaceImplementation(JVM.Import(typeof(System.Collections.IEnumerable)));
5118
// FXBUG we're using the same method name as the C# compiler here because both the .NET and Mono implementations of Xml serialization depend on this method name
5119
MethodBuilder mb = typeBuilder.DefineMethod("System.Collections.IEnumerable.GetEnumerator", MethodAttributes.Private | MethodAttributes.Virtual | MethodAttributes.NewSlot | MethodAttributes.Final | MethodAttributes.SpecialName, JVM.Import(typeof(System.Collections.IEnumerator)), Type.EmptyTypes);
5120
AttributeHelper.HideFromJava(mb);
5121
typeBuilder.DefineMethodOverride(mb, JVM.Import(typeof(System.Collections.IEnumerable)).GetMethod("GetEnumerator"));
5122
CodeEmitter ilgen = CodeEmitter.Create(mb);
5123
ilgen.Emit(OpCodes.Ldarg_0);
5124
MethodWrapper mw = enumeratorType.GetMethodWrapper("<init>", "(Ljava.lang.Iterable;)V", false);
5126
mw.EmitNewobj(ilgen);
5127
ilgen.Emit(OpCodes.Ret);
5132
// if we implement a ghost interface, add an implicit conversion to the ghost reference value type
5133
if (iface.IsGhost && wrapper.IsPublic)
5135
MethodBuilder mb = typeBuilder.DefineMethod("op_Implicit", MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.Static | MethodAttributes.SpecialName, iface.TypeAsSignatureType, new Type[] { wrapper.TypeAsSignatureType });
5136
AttributeHelper.HideFromJava(mb);
5137
CodeEmitter ilgen = CodeEmitter.Create(mb);
5138
CodeEmitterLocal local = ilgen.DeclareLocal(iface.TypeAsSignatureType);
5139
ilgen.Emit(OpCodes.Ldloca, local);
5140
ilgen.Emit(OpCodes.Ldarg_0);
5141
ilgen.Emit(OpCodes.Stfld, iface.GhostRefField);
5142
ilgen.Emit(OpCodes.Ldloca, local);
5143
ilgen.Emit(OpCodes.Ldobj, iface.TypeAsSignatureType);
5144
ilgen.Emit(OpCodes.Ret);
5148
#endif // STATIC_COMPILER
5149
// NOTE we're recursively "implementing" all interfaces that we inherit from the interfaces we implement.
5150
// The C# compiler also does this and the Compact Framework requires it.
5151
ImplementInterfaces(iface.Interfaces, interfaceList);
5156
private void AddUnsupportedAbstractMethods()
5158
foreach (MethodBase mb in wrapper.BaseTypeWrapper.TypeAsBaseType.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
5160
if (DotNetTypeWrapper.IsUnsupportedAbstractMethod(mb))
5162
GenerateUnsupportedAbstractMethodStub(mb);
5165
Dictionary<MethodBase, MethodBase> h = new Dictionary<MethodBase, MethodBase>();
5166
TypeWrapper tw = wrapper;
5169
foreach (TypeWrapper iface in tw.Interfaces)
5171
foreach (MethodBase mb in iface.TypeAsBaseType.GetMethods(BindingFlags.Public | BindingFlags.Instance))
5173
if (!h.ContainsKey(mb))
5176
if (DotNetTypeWrapper.IsUnsupportedAbstractMethod(mb))
5178
GenerateUnsupportedAbstractMethodStub(mb);
5183
tw = tw.BaseTypeWrapper;
5187
private void GenerateUnsupportedAbstractMethodStub(MethodBase mb)
5189
ParameterInfo[] parameters = mb.GetParameters();
5190
Type[] parameterTypes = new Type[parameters.Length];
5191
for (int i = 0; i < parameters.Length; i++)
5193
parameterTypes[i] = parameters[i].ParameterType;
5195
MethodAttributes attr = MethodAttributes.NewSlot | MethodAttributes.Virtual | MethodAttributes.Private;
5196
MethodBuilder m = typeBuilder.DefineMethod("__<unsupported>" + mb.DeclaringType.FullName + "/" + mb.Name, attr, ((MethodInfo)mb).ReturnType, parameterTypes);
5197
if (mb.IsGenericMethodDefinition)
5199
CopyGenericArguments(mb, m);
5201
CodeEmitter ilgen = CodeEmitter.Create(m);
5202
ilgen.EmitThrow("java.lang.AbstractMethodError", "Method " + mb.DeclaringType.FullName + "." + mb.Name + " is unsupported by IKVM.");
5204
typeBuilder.DefineMethodOverride(m, (MethodInfo)mb);
5207
private static void CopyGenericArguments(MethodBase mi, MethodBuilder mb)
5209
Type[] genericParameters = mi.GetGenericArguments();
5210
string[] genParamNames = new string[genericParameters.Length];
5211
for (int i = 0; i < genParamNames.Length; i++)
5213
genParamNames[i] = genericParameters[i].Name;
5215
GenericTypeParameterBuilder[] genParamBuilders = mb.DefineGenericParameters(genParamNames);
5216
for (int i = 0; i < genParamBuilders.Length; i++)
5218
// NOTE apparently we don't need to set the interface constraints
5219
// (and if we do, it fails for some reason)
5220
if (genericParameters[i].BaseType != Types.Object)
5222
genParamBuilders[i].SetBaseTypeConstraint(genericParameters[i].BaseType);
5224
genParamBuilders[i].SetGenericParameterAttributes(genericParameters[i].GenericParameterAttributes);
5228
private void CompileConstructorBody(FinishContext context, CodeEmitter ilGenerator, int methodIndex, Dictionary<MethodKey, MethodInfo> invokespecialstubcache)
5230
MethodWrapper[] methods = wrapper.GetMethods();
5231
ClassFile.Method m = classFile.Methods[methodIndex];
5232
TraceHelper.EmitMethodTrace(ilGenerator, classFile.Name + "." + m.Name + m.Signature);
5234
// do we have an implementation in map.xml?
5235
if (wrapper.EmitMapXmlMethodPrologueAndOrBody(ilGenerator, classFile, m))
5237
ilGenerator.DoEmit();
5241
bool nonLeaf = false;
5242
Compiler.Compile(context, wrapper, methods[methodIndex], classFile, m, ilGenerator, ref nonLeaf, invokespecialstubcache);
5243
ilGenerator.DoEmit();
5245
ilGenerator.EmitLineNumberTable((MethodBuilder)methods[methodIndex].GetMethod());
5246
#else // STATIC_COMPILER
5247
byte[] linenumbers = ilGenerator.GetLineNumberTable();
5248
if (linenumbers != null)
5250
if (wrapper.lineNumberTables == null)
5252
wrapper.lineNumberTables = new byte[methods.Length][];
5254
wrapper.lineNumberTables[methodIndex] = linenumbers;
5256
#endif // STATIC_COMPILER
5259
private static bool IsCompatibleArgList(TypeWrapper[] caller, TypeWrapper[] callee)
5261
if (caller.Length == callee.Length)
5263
for (int i = 0; i < caller.Length; i++)
5265
if (!caller[i].IsAssignableTo(callee[i]))
5275
private void EmitCallerIDInitialization(CodeEmitter ilGenerator, FieldInfo callerIDField)
5278
// we need to prohibit this optimization at runtime, because proxy classes may be injected into the boot class loader,
5279
// but they don't actually have access to core library internals
5281
TypeWrapper tw = CoreClasses.ikvm.@internal.CallerID.Wrapper;
5282
if (tw.GetClassLoader() == wrapper.GetClassLoader())
5284
MethodWrapper create = tw.GetMethodWrapper("create", "(Lcli.System.RuntimeTypeHandle;)Likvm.internal.CallerID;", false);
5285
ilGenerator.Emit(OpCodes.Ldtoken, this.typeBuilder);
5287
create.EmitCall(ilGenerator);
5292
RegisterNestedTypeBuilder(EmitCreateCallerID(typeBuilder, ilGenerator));
5294
ilGenerator.Emit(OpCodes.Stsfld, callerIDField);
5298
internal static TypeBuilder EmitCreateCallerID(TypeBuilder typeBuilder, CodeEmitter ilGenerator)
5300
TypeWrapper tw = CoreClasses.ikvm.@internal.CallerID.Wrapper;
5301
TypeBuilder typeCallerID = typeBuilder.DefineNestedType("__<CallerID>", TypeAttributes.Sealed | TypeAttributes.NestedPrivate, tw.TypeAsBaseType);
5302
MethodBuilder cb = ReflectUtil.DefineConstructor(typeCallerID, MethodAttributes.Assembly, null);
5303
CodeEmitter ctorIlgen = CodeEmitter.Create(cb);
5304
ctorIlgen.Emit(OpCodes.Ldarg_0);
5305
MethodWrapper mw = tw.GetMethodWrapper("<init>", "()V", false);
5307
mw.EmitCall(ctorIlgen);
5308
ctorIlgen.Emit(OpCodes.Ret);
5310
ilGenerator.Emit(OpCodes.Newobj, cb);
5311
return typeCallerID;
5314
private void EmitConstantValueInitialization(FieldWrapper[] fields, CodeEmitter ilGenerator)
5316
ClassFile.Field[] flds = classFile.Fields;
5317
for (int i = 0; i < flds.Length; i++)
5319
ClassFile.Field f = flds[i];
5320
if (f.IsStatic && !f.IsFinal)
5322
object constant = f.ConstantValue;
5323
if (constant != null)
5325
if (constant is int)
5327
ilGenerator.EmitLdc_I4((int)constant);
5329
else if (constant is bool)
5331
ilGenerator.EmitLdc_I4((bool)constant ? 1 : 0);
5333
else if (constant is byte)
5335
ilGenerator.EmitLdc_I4((byte)constant);
5337
else if (constant is char)
5339
ilGenerator.EmitLdc_I4((char)constant);
5341
else if (constant is short)
5343
ilGenerator.EmitLdc_I4((short)constant);
5345
else if (constant is long)
5347
ilGenerator.EmitLdc_I8((long)constant);
5349
else if (constant is double)
5351
ilGenerator.EmitLdc_R8((double)constant);
5353
else if (constant is float)
5355
ilGenerator.EmitLdc_R4((float)constant);
5357
else if (constant is string)
5359
ilGenerator.Emit(OpCodes.Ldstr, (string)constant);
5363
throw new InvalidOperationException();
5365
fields[i].EmitSet(ilGenerator);
5371
internal MethodBuilder DefineThreadLocalType()
5373
TypeWrapper threadLocal = ClassLoaderWrapper.LoadClassCritical("ikvm.internal.IntrinsicThreadLocal");
5374
int id = nestedTypeBuilders == null ? 0 : nestedTypeBuilders.Count;
5375
TypeBuilder tb = typeBuilder.DefineNestedType("__<tls>_" + id, TypeAttributes.NestedPrivate | TypeAttributes.Sealed, threadLocal.TypeAsBaseType);
5376
FieldBuilder fb = tb.DefineField("field", Types.Object, FieldAttributes.Private | FieldAttributes.Static);
5377
fb.SetCustomAttribute(new CustomAttributeBuilder(JVM.Import(typeof(ThreadStaticAttribute)).GetConstructor(Type.EmptyTypes), new object[0]));
5378
MethodBuilder mbGet = tb.DefineMethod("get", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.Final, Types.Object, Type.EmptyTypes);
5379
ILGenerator ilgen = mbGet.GetILGenerator();
5380
ilgen.Emit(OpCodes.Ldsfld, fb);
5381
ilgen.Emit(OpCodes.Ret);
5382
MethodBuilder mbSet = tb.DefineMethod("set", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.Final, null, new Type[] { Types.Object });
5383
ilgen = mbSet.GetILGenerator();
5384
ilgen.Emit(OpCodes.Ldarg_1);
5385
ilgen.Emit(OpCodes.Stsfld, fb);
5386
ilgen.Emit(OpCodes.Ret);
5387
MethodBuilder cb = ReflectUtil.DefineConstructor(tb, MethodAttributes.Assembly, Type.EmptyTypes);
5388
CodeEmitter ctorilgen = CodeEmitter.Create(cb);
5389
ctorilgen.Emit(OpCodes.Ldarg_0);
5390
MethodWrapper basector = threadLocal.GetMethodWrapper("<init>", "()V", false);
5392
basector.EmitCall(ctorilgen);
5393
ctorilgen.Emit(OpCodes.Ret);
5395
RegisterNestedTypeBuilder(tb);
5399
internal MethodBuilder GetAtomicReferenceFieldUpdater(FieldWrapper field)
5401
if (arfuMap == null)
5403
arfuMap = new Dictionary<FieldWrapper, MethodBuilder>();
5406
if (!arfuMap.TryGetValue(field, out cb))
5408
TypeWrapper arfuTypeWrapper = ClassLoaderWrapper.LoadClassCritical("ikvm.internal.IntrinsicAtomicReferenceFieldUpdater");
5409
TypeBuilder tb = typeBuilder.DefineNestedType("__<ARFU>_" + arfuMap.Count, TypeAttributes.NestedPrivate | TypeAttributes.Sealed, arfuTypeWrapper.TypeAsBaseType);
5410
AtomicReferenceFieldUpdaterEmitter.EmitImpl(tb, field.GetField());
5411
cb = ReflectUtil.DefineConstructor(tb, MethodAttributes.Assembly, Type.EmptyTypes);
5412
arfuMap.Add(field, cb);
5413
CodeEmitter ctorilgen = CodeEmitter.Create(cb);
5414
ctorilgen.Emit(OpCodes.Ldarg_0);
5415
MethodWrapper basector = arfuTypeWrapper.GetMethodWrapper("<init>", "()V", false);
5417
basector.EmitCall(ctorilgen);
5418
ctorilgen.Emit(OpCodes.Ret);
5420
RegisterNestedTypeBuilder(tb);
5425
internal TypeBuilder DefineIndyCallSiteType()
5427
int id = nestedTypeBuilders == null ? 0 : nestedTypeBuilders.Count;
5428
TypeBuilder tb = typeBuilder.DefineNestedType("__<>IndyCS" + id, TypeAttributes.NestedPrivate | TypeAttributes.Abstract | TypeAttributes.Sealed | TypeAttributes.BeforeFieldInit);
5429
RegisterNestedTypeBuilder(tb);
5433
internal TypeBuilder DefineMethodHandleConstantType(int index)
5435
TypeBuilder tb = typeBuilder.DefineNestedType("__<>MHC" + index, TypeAttributes.NestedPrivate | TypeAttributes.Sealed | TypeAttributes.Abstract | TypeAttributes.BeforeFieldInit); ;
5436
RegisterNestedTypeBuilder(tb);
5440
internal MethodBuilder DefineMethodHandleDispatchStub(Type returnType, Type[] parameterTypes)
5442
return typeBuilder.DefineMethod("__<>MHC", MethodAttributes.Static | MethodAttributes.PrivateScope, returnType, parameterTypes);
5445
internal FieldBuilder DefineMethodHandleInvokeCacheField(Type fieldType)
5447
return typeBuilder.DefineField("__<>invokeCache", fieldType, FieldAttributes.Static | FieldAttributes.PrivateScope);
5450
internal MethodBuilder DefineInvokeSpecialStub(DefineMethodHelper sig)
5452
return sig.DefineMethod(wrapper, typeBuilder, "__<>", MethodAttributes.PrivateScope);
5455
internal MethodBuilder DefineDelegateInvokeErrorStub(Type returnType, Type[] parameterTypes)
5457
return typeBuilder.DefineMethod("__<>", MethodAttributes.PrivateScope | MethodAttributes.Static, returnType, parameterTypes);
5461
private static bool CheckRequireOverrideStub(MethodWrapper mw1, MethodWrapper mw2)
5463
// TODO this is too late to generate LinkageErrors so we need to figure this out earlier
5464
if (!TypesMatchForOverride(mw1.ReturnType, mw2.ReturnType))
5468
TypeWrapper[] args1 = mw1.GetParameters();
5469
TypeWrapper[] args2 = mw2.GetParameters();
5470
for (int i = 0; i < args1.Length; i++)
5472
if (!TypesMatchForOverride(args1[i], args2[i]))
5480
private static bool TypesMatchForOverride(TypeWrapper tw1, TypeWrapper tw2)
5486
else if (tw1.IsUnloadable && tw2.IsUnloadable)
5488
return ((UnloadableTypeWrapper)tw1).CustomModifier == ((UnloadableTypeWrapper)tw2).CustomModifier;
5496
private void GenerateOverrideStub(TypeBuilder typeBuilder, MethodWrapper baseMethod, MethodInfo target, MethodWrapper targetMethod)
5498
Debug.Assert(!baseMethod.HasCallerID);
5500
MethodBuilder overrideStub = baseMethod.GetDefineMethodHelper().DefineMethod(this, typeBuilder, "__<overridestub>" + baseMethod.Name, MethodAttributes.Private | MethodAttributes.Virtual | MethodAttributes.NewSlot | MethodAttributes.Final);
5501
typeBuilder.DefineMethodOverride(overrideStub, (MethodInfo)baseMethod.GetMethod());
5503
Type stubret = baseMethod.ReturnTypeForDefineMethod;
5504
Type[] stubargs = baseMethod.GetParametersForDefineMethod();
5505
Type targetRet = targetMethod.ReturnTypeForDefineMethod;
5506
Type[] targetArgs = targetMethod.GetParametersForDefineMethod();
5507
CodeEmitter ilgen = CodeEmitter.Create(overrideStub);
5508
ilgen.Emit(OpCodes.Ldarg_0);
5509
for (int i = 0; i < targetArgs.Length; i++)
5511
ilgen.EmitLdarg(i + 1);
5512
if (targetArgs[i] != stubargs[i])
5514
ilgen.Emit(OpCodes.Castclass, targetArgs[i]);
5517
ilgen.Emit(OpCodes.Callvirt, target);
5518
if (targetRet != stubret)
5520
ilgen.Emit(OpCodes.Castclass, stubret);
5522
ilgen.Emit(OpCodes.Ret);
5526
protected static void GetParameterNamesFromLVT(ClassFile.Method m, string[] parameterNames)
5528
ClassFile.Method.LocalVariableTableEntry[] localVars = m.LocalVariableTableAttribute;
5529
if (localVars != null)
5531
for (int i = m.IsStatic ? 0 : 1, pos = 0; i < m.ArgMap.Length; i++)
5533
// skip double & long fillers
5534
if (m.ArgMap[i] != -1)
5536
if (parameterNames[pos] == null)
5538
for (int j = 0; j < localVars.Length; j++)
5540
if (localVars[j].index == i)
5542
parameterNames[pos] = localVars[j].name;
5553
protected static void GetParameterNamesFromSig(string sig, string[] parameterNames)
5555
List<string> names = new List<string>();
5556
for (int i = 1; sig[i] != ')'; i++)
5561
int end = sig.IndexOf(';', i);
5562
names.Add(GetParameterName(sig.Substring(i, end - i)));
5565
else if (sig[i] == '[')
5567
while (sig[++i] == '[') ;
5571
int end = sig.IndexOf(';', i);
5572
names.Add(GetParameterName(sig.Substring(i, end - i)) + "arr");
5633
for (int i = 0; i < parameterNames.Length; i++)
5635
if (parameterNames[i] == null)
5637
parameterNames[i] = (string)names[i];
5642
protected static ParameterBuilder[] GetParameterBuilders(MethodBuilder mb, int parameterCount, string[] parameterNames)
5644
ParameterBuilder[] parameterBuilders = new ParameterBuilder[parameterCount];
5645
Dictionary<string, int> clashes = null;
5646
for (int i = 0; i < parameterBuilders.Length; i++)
5649
if (parameterNames != null)
5651
name = parameterNames[i];
5652
if (Array.IndexOf(parameterNames, name, i + 1) >= 0 || (clashes != null && clashes.ContainsKey(name)))
5654
if (clashes == null)
5656
clashes = new Dictionary<string, int>();
5659
if (clashes.ContainsKey(name))
5661
clash = clashes[name] + 1;
5663
clashes[name] = clash;
5667
parameterBuilders[i] = mb.DefineParameter(i + 1, ParameterAttributes.None, name);
5669
return parameterBuilders;
5672
private static string GetParameterName(string type)
5674
if (type == "java.lang.String")
5678
else if (type == "java.lang.Object")
5684
System.Text.StringBuilder sb = new System.Text.StringBuilder();
5685
for (int i = type.LastIndexOf('.') + 1; i < type.Length; i++)
5687
if (char.IsUpper(type, i))
5689
sb.Append(char.ToLower(type[i]));
5692
return sb.ToString();
5697
protected abstract void AddMapXmlFields(ref FieldWrapper[] fields);
5698
protected abstract bool EmitMapXmlMethodPrologueAndOrBody(CodeEmitter ilgen, ClassFile f, ClassFile.Method m);
5699
protected abstract void EmitMapXmlMetadata(TypeBuilder typeBuilder, ClassFile classFile, FieldWrapper[] fields, MethodWrapper[] methods);
5700
protected abstract MethodBuilder DefineGhostMethod(string name, MethodAttributes attribs, MethodWrapper mw);
5701
protected abstract void FinishGhost(TypeBuilder typeBuilder, MethodWrapper[] methods);
5702
protected abstract void FinishGhostStep2();
5703
protected abstract TypeBuilder DefineGhostType(string mangledTypeName, TypeAttributes typeAttribs);
5704
#endif // STATIC_COMPILER
5706
protected virtual bool IsPInvokeMethod(ClassFile.Method m)
5709
// TODO PInvoke is not supported in RunAndCollect assemblies,
5710
if (JVM.classUnloading)
5715
if (m.Annotations != null)
5717
foreach (object[] annot in m.Annotations)
5719
if ("Lcli/System/Runtime/InteropServices/DllImportAttribute$Annotation;".Equals(annot[1]))
5728
internal override MethodBase LinkMethod(MethodWrapper mw)
5731
return impl.LinkMethod(mw);
5734
internal override FieldInfo LinkField(FieldWrapper fw)
5737
return impl.LinkField(fw);
5740
internal override void EmitRunClassConstructor(CodeEmitter ilgen)
5742
impl.EmitRunClassConstructor(ilgen);
5745
internal override string GetGenericSignature()
5747
return impl.GetGenericSignature();
5750
internal override string GetGenericMethodSignature(MethodWrapper mw)
5752
MethodWrapper[] methods = GetMethods();
5753
for (int i = 0; i < methods.Length; i++)
5755
if (methods[i] == mw)
5757
return impl.GetGenericMethodSignature(i);
5760
Debug.Fail("Unreachable code");
5764
internal override string GetGenericFieldSignature(FieldWrapper fw)
5766
FieldWrapper[] fields = GetFields();
5767
for (int i = 0; i < fields.Length; i++)
5769
if (fields[i] == fw)
5771
return impl.GetGenericFieldSignature(i);
5774
Debug.Fail("Unreachable code");
5778
#if !STATIC_COMPILER
5779
internal override string[] GetEnclosingMethod()
5781
return impl.GetEnclosingMethod();
5784
internal override string GetSourceFileName()
5786
return sourceFileName;
5789
private int GetMethodBaseToken(MethodBase mb)
5791
ConstructorInfo ci = mb as ConstructorInfo;
5794
return classLoader.GetTypeWrapperFactory().ModuleBuilder.GetConstructorToken(ci).Token;
5798
return classLoader.GetTypeWrapperFactory().ModuleBuilder.GetMethodToken((MethodInfo)mb).Token;
5802
internal override int GetSourceLineNumber(MethodBase mb, int ilOffset)
5804
if (lineNumberTables != null)
5806
int token = GetMethodBaseToken(mb);
5807
MethodWrapper[] methods = GetMethods();
5808
for (int i = 0; i < methods.Length; i++)
5810
if (GetMethodBaseToken(methods[i].GetMethod()) == token)
5812
if (lineNumberTables[i] != null)
5814
return new LineNumberTableAttribute(lineNumberTables[i]).GetLineNumber(ilOffset);
5823
internal override object[] GetDeclaredAnnotations()
5825
object[] annotations = impl.GetDeclaredAnnotations();
5826
if (annotations != null)
5828
object[] objs = new object[annotations.Length];
5829
for (int i = 0; i < annotations.Length; i++)
5831
objs[i] = JVM.NewAnnotation(GetClassLoader().GetJavaClassLoader(), annotations[i]);
5838
internal override object[] GetMethodAnnotations(MethodWrapper mw)
5840
MethodWrapper[] methods = GetMethods();
5841
for (int i = 0; i < methods.Length; i++)
5843
if (methods[i] == mw)
5845
object[] annotations = impl.GetMethodAnnotations(i);
5846
if (annotations != null)
5848
object[] objs = new object[annotations.Length];
5849
for (int j = 0; j < annotations.Length; j++)
5851
objs[j] = JVM.NewAnnotation(GetClassLoader().GetJavaClassLoader(), annotations[j]);
5858
Debug.Fail("Unreachable code");
5862
internal override object[][] GetParameterAnnotations(MethodWrapper mw)
5864
MethodWrapper[] methods = GetMethods();
5865
for (int i = 0; i < methods.Length; i++)
5867
if (methods[i] == mw)
5869
object[][] annotations = impl.GetParameterAnnotations(i);
5870
if (annotations != null)
5872
object[][] objs = new object[annotations.Length][];
5873
for (int j = 0; j < annotations.Length; j++)
5875
objs[j] = new object[annotations[j].Length];
5876
for (int k = 0; k < annotations[j].Length; k++)
5878
objs[j][k] = JVM.NewAnnotation(GetClassLoader().GetJavaClassLoader(), annotations[j][k]);
5886
Debug.Fail("Unreachable code");
5890
internal override object[] GetFieldAnnotations(FieldWrapper fw)
5892
FieldWrapper[] fields = GetFields();
5893
for (int i = 0; i < fields.Length; i++)
5895
if (fields[i] == fw)
5897
object[] annotations = impl.GetFieldAnnotations(i);
5898
if (annotations != null)
5900
object[] objs = new object[annotations.Length];
5901
for (int j = 0; j < annotations.Length; j++)
5903
objs[j] = JVM.NewAnnotation(GetClassLoader().GetJavaClassLoader(), annotations[j]);
5910
Debug.Fail("Unreachable code");
5914
internal override object GetAnnotationDefault(MethodWrapper mw)
5916
MethodWrapper[] methods = GetMethods();
5917
for (int i = 0; i < methods.Length; i++)
5919
if (methods[i] == mw)
5921
object defVal = impl.GetMethodDefaultValue(i);
5924
return JVM.NewAnnotationElementValue(mw.DeclaringType.GetClassLoader().GetJavaClassLoader(), mw.ReturnType.ClassObject, defVal);
5929
Debug.Fail("Unreachable code");
5934
protected virtual Type GetBaseTypeForDefineType()
5936
return BaseTypeWrapper.TypeAsBaseType;
5940
internal virtual MethodWrapper[] GetReplacedMethodsFor(MethodWrapper mw)
5944
#endif // STATIC_COMPILER
5946
internal override MethodBase GetSerializationConstructor()
5948
return automagicSerializationCtor;
5951
private Type[] GetModOpt(TypeWrapper tw, bool mustBePublic)
5953
return GetModOpt(GetClassLoader().GetTypeWrapperFactory(), tw, mustBePublic);
5956
internal static Type[] GetModOpt(TypeWrapperFactory context, TypeWrapper tw, bool mustBePublic)
5958
Type[] modopt = Type.EmptyTypes;
5959
if (tw.IsUnloadable)
5961
modopt = new Type[] { ((UnloadableTypeWrapper)tw).GetCustomModifier(context) };
5965
TypeWrapper tw1 = tw.IsArray ? tw.GetUltimateElementTypeWrapper() : tw;
5966
if (tw1.IsErasedOrBoxedPrimitiveOrRemapped || tw.IsGhostArray || (mustBePublic && !tw1.IsPublic))
5968
// FXBUG Ref.Emit refuses arrays in custom modifiers, so we add an array type for each dimension
5969
modopt = new Type[tw.ArrayRank + 1];
5970
modopt[0] = GetModOptHelper(tw1);
5971
for (int i = 1; i < modopt.Length; i++)
5973
modopt[i] = Types.Array;
5980
private static Type GetModOptHelper(TypeWrapper tw)
5982
Debug.Assert(!tw.IsUnloadable);
5985
return ArrayTypeWrapper.MakeArrayType(GetModOptHelper(tw.GetUltimateElementTypeWrapper()), tw.ArrayRank);
5987
else if (tw.IsGhost)
5989
return tw.TypeAsTBD;
5993
return tw.TypeAsBaseType;
5998
private bool NeedsType2AccessStub(FieldWrapper fw)
6000
Debug.Assert(this.IsPublic && fw.DeclaringType == this);
6001
return fw.IsType2FinalField
6002
|| (fw.HasNonPublicTypeInSignature
6003
&& (fw.IsPublic || (fw.IsProtected && !this.IsFinal))
6004
&& (fw.FieldTypeWrapper.IsUnloadable || fw.FieldTypeWrapper.IsAccessibleFrom(this) || fw.FieldTypeWrapper.InternalsVisibleTo(this)));
6009
sealed class DefineMethodHelper
6011
private readonly MethodWrapper mw;
6013
internal DefineMethodHelper(MethodWrapper mw)
6018
internal int ParameterCount
6020
get { return mw.GetParameters().Length + (mw.HasCallerID ? 1 : 0); }
6023
internal MethodBuilder DefineMethod(DynamicTypeWrapper context, TypeBuilder tb, string name, MethodAttributes attribs)
6025
return DefineMethod(context.GetClassLoader().GetTypeWrapperFactory(), tb, name, attribs);
6028
internal MethodBuilder DefineMethod(TypeWrapperFactory context, TypeBuilder tb, string name, MethodAttributes attribs)
6030
// we add optional modifiers to make the signature unique
6031
TypeWrapper[] parameters = mw.GetParameters();
6032
Type[] parameterTypes = new Type[parameters.Length + (mw.HasCallerID ? 1 : 0)];
6033
Type[][] modopt = new Type[parameterTypes.Length][];
6034
for (int i = 0; i < parameters.Length; i++)
6036
parameterTypes[i] = parameters[i].TypeAsSignatureType;
6037
modopt[i] = DynamicTypeWrapper.GetModOpt(context, parameters[i], false);
6041
parameterTypes[parameterTypes.Length - 1] = CoreClasses.ikvm.@internal.CallerID.Wrapper.TypeAsSignatureType;
6043
Type[] modoptReturnType = DynamicTypeWrapper.GetModOpt(context, mw.ReturnType, false);
6044
return tb.DefineMethod(name, attribs, CallingConventions.Standard, mw.ReturnType.TypeAsSignatureType, null, modoptReturnType, parameterTypes, null, modopt);
6047
internal MethodBuilder DefineConstructor(DynamicTypeWrapper context, TypeBuilder tb, MethodAttributes attribs)
6049
return DefineConstructor(context.GetClassLoader().GetTypeWrapperFactory(), tb, attribs);
6052
internal MethodBuilder DefineConstructor(TypeWrapperFactory context, TypeBuilder tb, MethodAttributes attribs)
6054
return DefineMethod(context, tb, ConstructorInfo.ConstructorName, attribs | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName);