25using System.Collections.Generic;
26using System.Diagnostics;
30using IKVM.ByteCode.Decoding;
42using System.Reflection;
43using System.Reflection.Emit;
51 partial class RuntimeByteCodeJavaType
54 internal sealed class FinishContext
57 readonly RuntimeContext context;
58 readonly RuntimeJavaType host;
59 readonly ClassFile classFile;
61 readonly TypeBuilder typeBuilder;
62 List<TypeBuilder> nestedTypeBuilders;
65 Dictionary<RuntimeJavaField, MethodBuilder> arfuMap;
66 Dictionary<MethodKey, MethodInfo> invokespecialstubcache;
67 Dictionary<string, MethodInfo> dynamicClassLiteral;
69 TypeBuilder interfaceHelperMethodsTypeBuilder;
71 List<object> liveObjects;
77 internal object value;
88 internal FinishContext(RuntimeContext context, RuntimeJavaType host, ClassFile classFile,
DynamicOrAotTypeWrapper wrapper, TypeBuilder typeBuilder)
90 this.context = context;
92 this.classFile = classFile;
93 this.wrapper = wrapper;
94 this.typeBuilder = typeBuilder;
100 public RuntimeContext Context => context;
102 internal RuntimeByteCodeJavaType TypeWrapper
104 get {
return wrapper; }
107 internal T GetValue<T>(
int key)
108 where T :
class,
new()
110 items ??=
new List<Item>();
111 for (
int i = 0; i < items.Count; i++)
112 if (items[i].key == key && items[i].value is T value)
123 internal void EmitDynamicClassLiteral(CodeEmitter ilgen, RuntimeJavaType tw,
bool dynamicCallerID)
125 Debug.Assert(tw.IsUnloadable);
127 dynamicClassLiteral ??=
new Dictionary<string, MethodInfo>();
129 var cacheKey = tw.Name;
131 cacheKey +=
";dynamic";
133 if (!dynamicClassLiteral.TryGetValue(cacheKey, out var method))
135 var fb = typeBuilder.DefineField(
"__<>class", context.JavaBase.TypeOfJavaLangClass.TypeAsSignatureType, FieldAttributes.PrivateScope | FieldAttributes.Static);
136 var mb = DefineHelperMethod(
"__<>class", context.JavaBase.TypeOfJavaLangClass.TypeAsSignatureType,
Type.EmptyTypes);
137 var ilgen2 = context.CodeEmitterFactory.Create(mb);
138 ilgen2.Emit(OpCodes.Ldsfld, fb);
139 var label = ilgen2.DefineLabel();
140 ilgen2.EmitBrtrue(label);
141 ilgen2.Emit(OpCodes.Ldstr, tw.Name);
142 EmitCallerID(ilgen2, dynamicCallerID);
143 ilgen2.Emit(OpCodes.Call, context.ByteCodeHelperMethods.DynamicClassLiteral);
144 ilgen2.Emit(OpCodes.Stsfld, fb);
145 ilgen2.MarkLabel(label);
146 ilgen2.Emit(OpCodes.Ldsfld, fb);
147 ilgen2.Emit(OpCodes.Ret);
150 dynamicClassLiteral.Add(cacheKey, method);
153 ilgen.Emit(OpCodes.Call, method);
156 internal void EmitHostCallerID(CodeEmitter ilgen)
158#if IMPORTER || FIRST_PASS
159 throw new InvalidOperationException();
161 EmitLiveObjectLoad(ilgen, DynamicCallerIDProvider.CreateCallerID(host));
162 context.JavaBase.TypeOfIkvmInternalCallerID.EmitCheckcast(ilgen);
166 internal void EmitCallerID(CodeEmitter ilgen,
bool dynamic)
168#if !FIRST_PASS && !IMPORTER
171 EmitLiveObjectLoad(ilgen, DynamicCallerIDProvider.Instance);
172 ilgen.Emit(OpCodes.Call, context.ByteCodeHelperMethods.DynamicCallerID);
176 if (callerIDMethod ==
null)
181 ilgen.Emit(OpCodes.Call, callerIDMethod);
184 private void CreateGetCallerID()
186 RuntimeJavaType tw = context.JavaBase.TypeOfIkvmInternalCallerID;
187 FieldBuilder callerIDField = typeBuilder.DefineField(
"__<callerID>", tw.TypeAsSignatureType, FieldAttributes.Private | FieldAttributes.Static | FieldAttributes.SpecialName);
188 MethodBuilder mb = DefineHelperMethod(
"__<GetCallerID>", tw.TypeAsSignatureType,
Type.EmptyTypes);
190 CodeEmitter ilgen = context.CodeEmitterFactory.Create(mb);
191 ilgen.Emit(OpCodes.Ldsfld, callerIDField);
192 CodeEmitterLabel done = ilgen.DefineLabel();
193 ilgen.EmitBrtrue(done);
194 EmitCallerIDInitialization(ilgen, callerIDField);
195 ilgen.MarkLabel(done);
196 ilgen.Emit(OpCodes.Ldsfld, callerIDField);
197 ilgen.Emit(OpCodes.Ret);
201 private void RegisterNestedTypeBuilder(TypeBuilder tb)
203 nestedTypeBuilders ??=
new List<TypeBuilder>();
204 nestedTypeBuilders.Add(tb);
207 internal Type FinishImpl()
209 var methods = wrapper.GetMethods();
210 var fields = wrapper.GetFields();
212 wrapper.FinishGhost(typeBuilder, methods);
215 if (!classFile.IsInterface)
219 typeBuilder.SetParent(wrapper.GetBaseTypeForDefineType());
223 if (!wrapper.IsAbstract)
225 var parent = wrapper.BaseTypeWrapper;
231 while (parent !=
null && parent.IsAbstract)
233 foreach (RuntimeJavaMethod mw
in parent.GetMethods())
236 if (mi !=
null && mi.IsAbstract && !mi.DeclaringType.IsInterface)
238 bool needStub =
false;
239 bool needRename =
false;
240 if (mw.IsPublic || mw.IsProtected)
242 var fmw = wrapper.GetMethod(mw.Name, mw.Signature,
true);
243 while (fmw != mw && (fmw.IsStatic || fmw.IsPrivate))
246 fmw = fmw.DeclaringType.BaseTypeWrapper.GetMethod(mw.Name, mw.Signature,
true);
248 if (fmw == mw && fmw.DeclaringType != wrapper)
255 var fmw = wrapper.GetMethod(mw.Name, mw.Signature,
true);
256 while (fmw != mw && (fmw.IsStatic || fmw.IsPrivate || !(mw.DeclaringType.IsPackageAccessibleFrom(fmw.DeclaringType) || (mw.IsInternal && mw.DeclaringType.InternalsVisibleTo(fmw.DeclaringType)))))
259 fmw = fmw.DeclaringType.BaseTypeWrapper.GetMethod(mw.Name, mw.Signature,
true);
261 if (fmw == mw && fmw.DeclaringType != wrapper)
270 string name = mi.Name;
271 MethodAttributes attr = mi.Attributes & ~(MethodAttributes.Abstract | MethodAttributes.NewSlot);
274 name =
"__<>" + name +
"/" + mi.DeclaringType.FullName;
275 attr = MethodAttributes.Private | MethodAttributes.Virtual | MethodAttributes.NewSlot;
277 MethodBuilder mb = mw.GetDefineMethodHelper().DefineMethod(wrapper, typeBuilder, name, attr);
280 typeBuilder.DefineMethodOverride(mb, mi);
282 context.AttributeHelper.HideFromJava(mb);
283 CodeEmitter ilgen = context.CodeEmitterFactory.Create(mb);
284 ilgen.EmitThrow(
"java.lang.AbstractMethodError", mw.DeclaringType.Name +
"." + mw.Name + mw.Signature);
286 wrapper.EmitLevel4Warning(
HardError.AbstractMethodError, mw.DeclaringType.Name +
"." + mw.Name + mw.Signature);
291 parent = parent.BaseTypeWrapper;
295 TypeBuilder tbDefaultMethods =
null;
297 bool basehasclinit = wrapper.BaseTypeWrapper !=
null && wrapper.BaseTypeWrapper.HasStaticInitializer;
298 int clinitIndex = -1;
299 bool hasConstructor =
false;
300 for (
int i = 0; i < classFile.Methods.Length; i++)
302 var m = classFile.Methods[i];
303 var mb = (MethodBuilder)methods[i].GetMethod();
309 hasConstructor =
true;
312 else if (m.IsClassInitializer)
319 else if (m.IsConstructor)
321 hasConstructor =
true;
322 var ilGenerator = context.CodeEmitterFactory.Create(mb);
323 CompileConstructorBody(
this, ilGenerator, i);
328 if (methods[i].GetParameters().Length > MethodHandleUtil.MaxArity && methods[i].RequiresNonVirtualDispatcher && wrapper.ClassLoader.EmitNoRefEmitHelpers)
330 wrapper.ClassLoader.GetTypeWrapperFactory().DefineDelegate(methods[i].GetParameters().Length, methods[i].ReturnType == context.PrimitiveJavaTypeFactory.VOID);
336 if (!classFile.IsAbstract)
341 wrapper.EmitLevel4Warning(
HardError.AbstractMethodError, classFile.Name +
"." + m.Name + m.Signature);
343 else if (classFile.IsPublic && !classFile.IsFinal && !(m.IsPublic || m.IsProtected))
352 var ilGenerator = context.CodeEmitterFactory.Create(mb);
353 ilGenerator.EmitThrow(
"java.lang.AbstractMethodError", classFile.Name +
"." + m.Name + m.Signature);
354 ilGenerator.DoEmit();
359 if ((mb.Attributes & MethodAttributes.PinvokeImpl) != 0)
364 if (wrapper.IsDelegate)
366 mb.SetImplementationFlags(mb.GetMethodImplementationFlags() | MethodImplAttributes.Runtime);
370 Profiler.Enter(
"JavaTypeImpl.Finish.Native");
373 var ilGenerator = context.CodeEmitterFactory.Create(mb);
376 if (wrapper.EmitMapXmlMethodPrologueAndOrBody(ilGenerator, classFile, m))
378 ilGenerator.DoEmit();
382 if (m.InterlockedCompareAndSetField !=
null && EmitInterlockedCompareAndSet(methods[i], m.InterlockedCompareAndSetField, ilGenerator))
384 ilGenerator.DoEmit();
390 var args = methods[i].GetParameters();
395 var nativeCodeType = context.Resolver.ResolveRuntimeType(
"IKVM.Java.Externs." + classFile.Name.Replace(
"$",
"+")).AsReflection();
396 if (nativeCodeType !=
null)
399 nargs = ArrayUtil.Concat(wrapper, args);
401 if (methods[i].HasCallerID)
402 nargs = ArrayUtil.Concat(nargs, context.JavaBase.TypeOfIkvmInternalCallerID);
404 foreach (var method
in nativeCodeType.GetMethods(BindingFlags.Static | BindingFlags.Public))
406 var param = method.GetParameters();
407 int paramLength = param.Length;
409 while (paramLength != 0 && (param[paramLength - 1].IsIn || param[paramLength - 1].ParameterType.IsByRef))
412 var match =
new RuntimeJavaType[paramLength];
413 for (
int j = 0; j < paramLength; j++)
414 match[j] = context.ClassLoaderFactory.GetJavaTypeFromType(param[j].ParameterType);
416 if (m.Name == method.Name && IsCompatibleArgList(nargs, match))
418 nativeMethod = method;
426 if (nativeMethod !=
null)
429 for (
int j = 0; j < nargs.Length; j++)
430 ilGenerator.EmitLdarg(j);
432 var param = nativeMethod.GetParameters();
433 for (
int j = nargs.Length; j < param.Length; j++)
435 var paramType = param[j].ParameterType;
436 var fieldTypeWrapper = context.ClassLoaderFactory.GetJavaTypeFromType(paramType.IsByRef ? paramType.GetElementType() : paramType);
437 var field = wrapper.GetFieldWrapper(param[j].
Name, fieldTypeWrapper.SigName);
440 wrapper.Context.Diagnostics.GenericCompilerError($
"Error: Native method field binding not found: {classFile.Name}.{param[j].Name}{fieldTypeWrapper.SigName}");
441 wrapper.Context.StaticCompiler.errorCount++;
444 if (m.IsStatic && !field.IsStatic)
446 wrapper.Context.Diagnostics.GenericCompilerError($
"Error: Native method field binding cannot access instance field from static method: {classFile.Name}.{param[j].Name}{fieldTypeWrapper.SigName}");
447 wrapper.Context.StaticCompiler.errorCount++;
450 if (!field.IsAccessibleFrom(wrapper, wrapper, wrapper))
452 wrapper.Context.Diagnostics.GenericCompilerError($
"Error: Native method field binding not accessible: {classFile.Name}.{param[j].Name}{fieldTypeWrapper.SigName}");
453 wrapper.Context.StaticCompiler.errorCount++;
456 if (paramType.IsByRef && field.IsFinal)
458 wrapper.Context.Diagnostics.GenericCompilerError($
"Error: Native method field binding cannot use ByRef for final field: {classFile.Name}.{param[j].Name}{fieldTypeWrapper.SigName}");
459 wrapper.Context.StaticCompiler.errorCount++;
463 if (paramType.IsByRef && field.GetField() ==
null)
465 wrapper.Context.Diagnostics.GenericCompilerError($
"Error: Native method field binding cannot use ByRef on field without backing field: {classFile.Name}.{param[j].Name}{fieldTypeWrapper.SigName}");
466 wrapper.Context.StaticCompiler.errorCount++;
471 ilGenerator.EmitLdarg(0);
473 if (paramType.IsByRef)
475 ilGenerator.Emit(field.IsStatic ? OpCodes.Ldsflda : OpCodes.Ldflda, field.GetField());
479 field.EmitGet(ilGenerator);
482 ilGenerator.Emit(OpCodes.Call, nativeMethod);
483 var retTypeWrapper = methods[i].ReturnType;
484 if (!retTypeWrapper.TypeAsTBD.Equals(nativeMethod.ReturnType) && !retTypeWrapper.IsGhost)
485 ilGenerator.Emit(OpCodes.Castclass, retTypeWrapper.TypeAsTBD);
487 ilGenerator.Emit(OpCodes.Ret);
492 if (wrapper.ClassLoader.NoJNI)
495 wrapper.ClassLoader.Diagnostics.GenericCompilerWarning($
"Native method not implemented: {classFile.Name}.{m.Name}.{m.Signature}");
496 ilGenerator.EmitThrow(
"java.lang.UnsatisfiedLinkError",
"Native method not implemented (compiled with -nojni): " + classFile.Name +
"." + m.Name + m.Signature);
500 new JniBuilder(context).Generate(
this, ilGenerator, wrapper, methods[i], typeBuilder, classFile, m, args,
false);
504 ilGenerator.DoEmit();
508 Profiler.Leave(
"JavaTypeImpl.Finish.Native");
513 if (m.IsVirtual && classFile.IsInterface)
515 mb = (MethodBuilder)RuntimeDefaultInterfaceJavaMethod.GetImpl(methods[i]);
517 CreateDefaultMethodInterop(
ref tbDefaultMethods, mb, methods[i]);
521 var ilGenerator = context.CodeEmitterFactory.Create(mb);
522 if (!m.IsStatic && !m.IsPublic && classFile.IsInterface)
526 ilGenerator.EmitLdarg(0);
528 ilGenerator.Emit(OpCodes.Ldfld, wrapper.GhostRefField);
529 ilGenerator.EmitNullCheck();
534 if (wrapper.EmitMapXmlMethodPrologueAndOrBody(ilGenerator, classFile, m))
536 ilGenerator.DoEmit();
541 Compiler.Compile(
this, host, wrapper, methods[i], classFile, m, ilGenerator,
ref nonleaf);
542 ilGenerator.CheckLabels();
543 ilGenerator.DoEmit();
545 mb.SetImplementationFlags(mb.GetMethodImplementationFlags());
547 ilGenerator.EmitLineNumberTable(mb);
549 var linenumbers = ilGenerator.GetLineNumberTable();
550 if (linenumbers !=
null)
552 wrapper.lineNumberTables ??=
new byte[methods.Length][];
553 wrapper.lineNumberTables[i] = linenumbers;
560 AddInheritedDefaultInterfaceMethods(methods);
562 if (clinitIndex != -1 || (basehasclinit && !classFile.IsInterface) || classFile.HasInitializedFields)
565 if (clinitIndex != -1)
567 cb = (MethodBuilder)methods[clinitIndex].GetMethod();
571 cb = ReflectUtil.DefineTypeInitializer(typeBuilder, wrapper.classLoader);
572 context.AttributeHelper.HideFromJava(cb);
574 var ilGenerator = context.CodeEmitterFactory.Create(cb);
577 EmitConstantValueInitialization(fields, ilGenerator);
579 wrapper.BaseTypeWrapper.EmitRunClassConstructor(ilGenerator);
581 if (clinitIndex != -1)
583 CompileConstructorBody(
this, ilGenerator, clinitIndex);
587 ilGenerator.Emit(OpCodes.Ret);
588 ilGenerator.DoEmit();
591 ilGenerator.CheckLabels();
595 ImplementInterfaces(wrapper.Interfaces,
new List<RuntimeJavaType>());
598 if (!classFile.IsInterface)
607 var ilgen = context.CodeEmitterFactory.Create(ReflectUtil.DefineConstructor(typeBuilder, MethodAttributes.PrivateScope,
Type.EmptyTypes));
608 ilgen.Emit(OpCodes.Ldnull);
609 ilgen.Emit(OpCodes.Throw);
618 var doneSet =
new Dictionary<RuntimeJavaType, RuntimeJavaType>();
619 var interfaces = wrapper.Interfaces;
620 for (
int i = 0; i < interfaces.Length; i++)
621 ImplementInterfaceMethodStubs(doneSet, interfaces[i],
false);
625 var baseTypeWrapper = wrapper.BaseTypeWrapper;
626 while (baseTypeWrapper.HasIncompleteInterfaceImplementation)
628 for (
int i = 0; i < baseTypeWrapper.Interfaces.Length; i++)
629 ImplementInterfaceMethodStubs(doneSet, baseTypeWrapper.Interfaces[i],
true);
631 baseTypeWrapper = baseTypeWrapper.BaseTypeWrapper;
634 if (!wrapper.IsAbstract && wrapper.HasUnsupportedAbstractMethods)
635 AddUnsupportedAbstractMethods();
637 if (!wrapper.ClassLoader.NoAutomagicSerialization)
638 wrapper.automagicSerializationCtor = context.Serialization.AddAutomagicSerialization(wrapper, typeBuilder);
645 AddInterfaceFieldsInterop(fields);
649 AddInterfaceMethodsInterop(methods);
652 wrapper.EmitMapXmlMetadata(typeBuilder, classFile, fields, methods);
655 if (wrapper.IsPublic)
658 AddConstantPoolAttributeIfNecessary(context, classFile, typeBuilder);
662 for (
int i = 0; i < classFile.Methods.Length; i++)
664 var m = classFile.Methods[i];
665 var mb = (MethodBuilder)methods[i].GetMethod();
669 if (m.Annotations !=
null)
671 ParameterBuilder returnParameter =
null;
672 foreach (
object[] def
in m.Annotations)
674 var annotation = Annotation.Load(wrapper, def);
675 if (annotation !=
null)
677 annotation.Apply(wrapper.ClassLoader, mb, def);
678 annotation.ApplyReturnValue(wrapper.ClassLoader, mb,
ref returnParameter, def);
683 AddMethodParameterInfo(m, methods[i], mb, out var parameterNames);
686 if (methods[i].HasCallerID)
688 context.AttributeHelper.SetEditorBrowsableNever(mb);
689 EmitCallerIDStub(methods[i], parameterNames);
694 for (
int i = 0; i < classFile.Fields.Length; i++)
696 if (classFile.Fields[i].Annotations !=
null)
698 foreach (
object[] def
in classFile.Fields[i].Annotations)
700 var annotation = Annotation.Load(wrapper, def);
701 if (annotation !=
null)
704 var prop = fields[i] as RuntimeByteCodePropertyJavaField;
707 annotation.Apply(wrapper.ClassLoader, prop.GetPropertyBuilder(), def);
711 annotation.Apply(wrapper.ClassLoader, (FieldBuilder)fields[i].GetField(), def);
719 if (classFile.Annotations !=
null)
721 foreach (
object[] def
in classFile.Annotations)
723 var annotation = Annotation.Load(wrapper, def);
724 if (annotation !=
null)
725 annotation.Apply(wrapper.ClassLoader, typeBuilder, def);
730 AddImplementsAttribute();
734 Profiler.Enter(
"TypeBuilder.CreateType");
738 type = typeBuilder.CreateType();
739 if (nestedTypeBuilders !=
null)
741 context.ClassLoaderFactory.LoadClassCritical(
"ikvm.internal.IntrinsicAtomicReferenceFieldUpdater").Finish();
742 context.ClassLoaderFactory.LoadClassCritical(
"ikvm.internal.IntrinsicThreadLocal").Finish();
743 foreach (TypeBuilder tb
in nestedTypeBuilders)
747 if (liveObjects !=
null)
748 typeof(
IKVM.
Runtime.
LiveObjectHolder<>).MakeGenericType(type).GetField(
"values", BindingFlags.Static | BindingFlags.Public).SetValue(
null, liveObjects.ToArray());
753 Profiler.Leave(
"TypeBuilder.CreateType");
757 context.ClassLoaderFactory.SetWrapperForType(type, wrapper);
761 wrapper.FinishGhostStep2();
769 static void AddConstantPoolAttributeIfNecessary(RuntimeContext context, ClassFile classFile, TypeBuilder typeBuilder)
771 object[] constantPool =
null;
774 ref readonly var runtimeVisibleTypeAnnotations =
ref classFile.RuntimeVisibleTypeAnnotations;
775 MarkConstantPoolUsage(classFile, in runtimeVisibleTypeAnnotations,
ref constantPool,
ref inUse);
777 foreach (var method
in classFile.Methods)
779 ref readonly var methodRuntimeVisibleTypeAnnotations =
ref method.RuntimeVisibleTypeAnnotations;
780 MarkConstantPoolUsage(classFile, in methodRuntimeVisibleTypeAnnotations,
ref constantPool,
ref inUse);
783 foreach (var field
in classFile.Fields)
785 ref readonly var fieldRuntimeVisibleTypeAnnotations =
ref field.RuntimeVisibleTypeAnnotations;
786 MarkConstantPoolUsage(classFile, in field.RuntimeVisibleTypeAnnotations,
ref constantPool,
ref inUse);
789 if (constantPool !=
null)
793 context.AttributeHelper.SetConstantPoolAttribute(typeBuilder,
ConstantPoolAttribute.Compress(constantPool, inUse));
804 static void MarkConstantPoolUsage(ClassFile classFile,
ref readonly TypeAnnotationTable runtimeVisibleTypeAnnotations,
ref object[] constantPool,
ref bool[] inUse)
806 if (runtimeVisibleTypeAnnotations.Count > 0)
808 if (constantPool ==
null)
810 constantPool = classFile.GetConstantPool();
811 inUse =
new bool[constantPool.Length];
815 foreach (
ref readonly var annotation
in runtimeVisibleTypeAnnotations)
817 ref readonly var i =
ref annotation;
818 MarkConstantPoolUsageForTypeAnnotation(in i, inUse);
827 catch (IndexOutOfRangeException)
831 catch (ByteCodeException)
837 for (
int i = 0; i < inUse.Length; i++)
842 static void MarkConstantPoolUsageForAnnotation(
ref readonly
IKVM.ByteCode.Decoding.Annotation annotation,
bool[] inUse)
844 inUse[annotation.Type.Slot] =
true;
846 for (
int i = 0; i < annotation.Elements.Count; i++)
848 ref readonly var element =
ref annotation.Elements[i];
849 ref readonly var elementValue =
ref element.Value;
850 inUse[element.Name.Slot] =
true;
851 MarkConstantPoolUsageForAnnotationComponentValue(in elementValue, inUse);
855 static void MarkConstantPoolUsageForTypeAnnotation(
ref readonly TypeAnnotation annotation,
bool[] inUse)
857 inUse[annotation.Type.Slot] =
true;
859 for (
int i = 0; i < annotation.Elements.Count; i++)
861 ref readonly var element =
ref annotation.Elements[i];
862 ref readonly var elementValue =
ref element.Value;
863 inUse[element.Name.Slot] =
true;
864 MarkConstantPoolUsageForAnnotationComponentValue(in elementValue, inUse);
868 static void MarkConstantPoolUsageForAnnotationComponentValue(
ref readonly ElementValue element,
bool[] inUse)
870 switch (element.Kind)
872 case ElementValueKind.Boolean:
873 case ElementValueKind.Byte:
874 case ElementValueKind.Char:
875 case ElementValueKind.Double:
876 case ElementValueKind.Float:
877 case ElementValueKind.Integer:
878 case ElementValueKind.Long:
879 case ElementValueKind.Short:
880 case ElementValueKind.String:
881 inUse[((ConstantElementValue)element).Handle.Slot] =
true;
883 case ElementValueKind.Class:
884 inUse[((ClassElementValue)element).
Class.Slot] =
true;
886 case ElementValueKind.Enum:
887 var enum_ = (EnumElementValue)element;
888 inUse[enum_.TypeName.Slot] =
true;
889 inUse[enum_.ConstantName.Slot] =
true;
891 case ElementValueKind.Annotation:
892 var annotation = ((AnnotationElementValue)element).Annotation;
893 MarkConstantPoolUsageForAnnotation(
ref annotation, inUse);
895 case ElementValueKind.Array:
896 foreach (
ref readonly var i
in (ArrayElementValue)element)
897 MarkConstantPoolUsageForAnnotationComponentValue(in i, inUse);
902 private bool EmitInterlockedCompareAndSet(RuntimeJavaMethod method,
string fieldName, CodeEmitter ilGenerator)
904 if (method.ReturnType != context.PrimitiveJavaTypeFactory.BOOLEAN)
907 var parameters = method.GetParameters();
908 RuntimeJavaType target;
913 if (parameters.Length != 3)
916 target = parameters[0];
921 if (parameters.Length != 2)
924 target = method.DeclaringType;
928 if (target.IsUnloadable || target.IsPrimitive || target.IsNonPrimitiveValueType || target.IsGhost)
933 var fieldType = parameters[firstValueIndex];
934 if (fieldType != parameters[firstValueIndex + 1])
938 if (fieldType.IsUnloadable || fieldType.IsNonPrimitiveValueType || fieldType.IsGhost)
942 if (fieldType.IsPrimitive && fieldType != context.PrimitiveJavaTypeFactory.LONG && fieldType != context.PrimitiveJavaTypeFactory.INT)
947 RuntimeJavaField casField =
null;
948 foreach (var fw
in target.GetFields())
950 if (fw.Name == fieldName)
952 if (casField !=
null)
959 if (casField ==
null)
962 if (casField.IsStatic)
966 if (casField.FieldTypeWrapper != fieldType)
969 if (casField.IsPropertyAccessor)
972 if (casField.DeclaringType.TypeAsBaseType == typeBuilder.DeclaringType)
976 else if (!casField.IsAccessibleFrom(casField.DeclaringType, wrapper, casField.DeclaringType))
986 ilGenerator.EmitLdarg(0);
987 ilGenerator.Emit(OpCodes.Ldflda, fi);
988 ilGenerator.EmitLdarg(2);
989 ilGenerator.EmitLdarg(1);
990 if (fieldType == context.PrimitiveJavaTypeFactory.LONG)
992 ilGenerator.Emit(OpCodes.Call, context.InterlockedMethods.CompareExchangeInt64);
994 else if (fieldType == context.PrimitiveJavaTypeFactory.INT)
996 ilGenerator.Emit(OpCodes.Call, context.InterlockedMethods.CompareExchangeInt32);
1000 ilGenerator.Emit(OpCodes.Call, AtomicReferenceFieldUpdaterEmitter.MakeCompareExchange(context, casField.FieldTypeWrapper.TypeAsSignatureType));
1002 ilGenerator.EmitLdarg(1);
1003 ilGenerator.Emit(OpCodes.Ceq);
1004 ilGenerator.Emit(OpCodes.Ret);
1009 private void AddMethodParameterInfo(ClassFile.Method m, RuntimeJavaMethod mw, MethodBuilder mb, out
string[] parameterNames)
1011 parameterNames =
null;
1012 ParameterBuilder[] parameterBuilders =
null;
1014 if (wrapper.ClassLoader.EmitSymbols
1016 || (classFile.IsPublic && (m.IsPublic || m.IsProtected))
1017 || (m.MethodParameters !=
null && !wrapper.ClassLoader.NoParameterReflection)
1021 parameterNames =
new string[mw.GetParameters().Length];
1022 GetParameterNamesFromMP(m, parameterNames);
1024 if (m.MethodParameters ==
null)
1031 wrapper.GetParameterNamesFromXml(m.Name, m.Signature, parameterNames);
1037 if ((m.Modifiers &
Modifiers.VarArgs) != 0 && !mw.HasCallerID)
1040 if (parameterBuilders.Length > 0)
1041 context.AttributeHelper.SetParamArrayAttribute(parameterBuilders[parameterBuilders.Length - 1]);
1044 wrapper.AddXmlMapParameterAttributes(mb, classFile.Name, m.Name, m.Signature,
ref parameterBuilders);
1047 if (m.ParameterAnnotations !=
null)
1051 object[][] defs = m.ParameterAnnotations;
1052 for (
int j = 0; j < defs.Length; j++)
1054 foreach (
object[] def
in defs[j])
1056 var annotation = Annotation.Load(wrapper, def);
1057 if (annotation !=
null)
1058 annotation.Apply(wrapper.ClassLoader, parameterBuilders[j], def);
1066 private void AddImplementsAttribute()
1068 var interfaces = wrapper.Interfaces;
1069 if (wrapper.BaseTypeWrapper == context.JavaBase.TypeOfJavaLangObject)
1073 Type[] actualInterfaces = typeBuilder.GetInterfaces();
1074 if (actualInterfaces.Length == 0)
1078 else if (actualInterfaces.Length == 1
1079 && interfaces.Length == 1
1080 && !interfaces[0].IsRemapped
1081 && interfaces[0].TypeAsBaseType == actualInterfaces[0])
1089 else if (interfaces.Length == 0)
1093 context.AttributeHelper.SetImplementsAttribute(typeBuilder, interfaces);
1096 private TypeBuilder DefineNestedInteropType(
string name)
1099 while (!ccl.ReserveName(classFile.Name +
"$" + name))
1103 TypeBuilder tb = typeBuilder.DefineNestedType(name, TypeAttributes.Class | TypeAttributes.NestedPublic | TypeAttributes.Sealed | TypeAttributes.Abstract);
1104 RegisterNestedTypeBuilder(tb);
1105 context.AttributeHelper.HideFromJava(tb);
1109 void AddInterfaceFieldsInterop(RuntimeJavaField[] fields)
1114 void AddInterfaceMethodsInterop(RuntimeJavaMethod[] methods)
1119 private void CreateDefaultMethodInterop(
ref TypeBuilder tbDefaultMethods, MethodBuilder defaultMethod, RuntimeJavaMethod mw)
1121 if (!ParametersAreAccessible(mw))
1126 if (tbDefaultMethods ==
null)
1128 tbDefaultMethods = DefineNestedInteropType(NestedTypeName.DefaultMethods);
1131 var mb = mw.GetDefineMethodHelper().DefineMethod(wrapper.ClassLoader.GetTypeWrapperFactory(), tbDefaultMethods, mw.Name, MethodAttributes.Public | MethodAttributes.Static, wrapper.TypeAsSignatureType,
true);
1132 var ilgen = context.CodeEmitterFactory.Create(mb);
1133 if (wrapper.IsGhost)
1135 ilgen.EmitLdarga(0);
1136 ilgen.Emit(OpCodes.Ldfld, wrapper.GhostRefField);
1137 ilgen.EmitNullCheck();
1138 ilgen.EmitLdarga(0);
1143 ilgen.Emit(OpCodes.Dup);
1144 ilgen.EmitNullCheck();
1146 RuntimeJavaType[] parameters = mw.GetParameters();
1147 for (
int i = 0; i < parameters.Length; i++)
1149 ilgen.EmitLdarg(i + 1);
1150 if (!parameters[i].IsUnloadable && !parameters[i].IsPublic)
1152 parameters[i].EmitCheckcast(ilgen);
1155 ilgen.Emit(OpCodes.Call, defaultMethod);
1156 ilgen.Emit(OpCodes.Ret);
1161 private void AddInheritedDefaultInterfaceMethods(RuntimeJavaMethod[] methods)
1164 for (
int i = classFile.Methods.Length; i < methods.Length; i++)
1166 if (methods[i].IsMirandaMethod)
1168 RuntimeMirandaJavaMethod mmw = (RuntimeMirandaJavaMethod)methods[i];
1169 if (mmw.Error ==
null && !mmw.BaseMethod.IsAbstract)
1172 MethodBuilder mb = (MethodBuilder)mmw.GetMethod();
1173 if (classFile.IsInterface)
1176 mb = methods[i].GetDefineMethodHelper().DefineMethod(wrapper.ClassLoader.GetTypeWrapperFactory(),
1177 typeBuilder, NamePrefix.DefaultMethod + mb.Name, MethodAttributes.Public | MethodAttributes.Static | MethodAttributes.SpecialName, typeBuilder,
false);
1179 EmitCallDefaultInterfaceMethod(mb, mmw.BaseMethod);
1185 internal void EmitCallDefaultInterfaceMethod(MethodBuilder mb, RuntimeJavaMethod defaultMethod)
1187 CodeEmitter ilgen = context.CodeEmitterFactory.Create(mb);
1188 if (defaultMethod.DeclaringType.IsGhost)
1190 CodeEmitterLocal local = ilgen.DeclareLocal(defaultMethod.DeclaringType.TypeAsSignatureType);
1191 ilgen.Emit(OpCodes.Ldloca, local);
1193 ilgen.Emit(OpCodes.Stfld, defaultMethod.DeclaringType.GhostRefField);
1194 ilgen.Emit(OpCodes.Ldloca, local);
1200 for (
int j = 0, count = defaultMethod.GetParameters().Length; j < count; j++)
1202 ilgen.EmitLdarg(j + 1);
1204 ilgen.Emit(OpCodes.Call, RuntimeDefaultInterfaceJavaMethod.GetImpl(defaultMethod));
1205 ilgen.Emit(OpCodes.Ret);
1210 void AddAccessStubs()
1239 AddType2FieldAccessStubs();
1240 AddType1FieldAccessStubs(wrapper);
1241 if (!wrapper.IsInterface)
1244 AddType2MethodAccessStubs(
ref id);
1245 AddType1MethodAccessStubs(
ref id);
1249 void AddType1FieldAccessStubs(RuntimeJavaType tw)
1255 foreach (RuntimeJavaField fw
in tw.GetFields())
1257 if ((fw.IsPublic || (fw.IsProtected && !wrapper.IsFinal)) && wrapper.GetFieldWrapper(fw.Name, fw.Signature) == fw)
1259 GenerateAccessStub(fw,
true);
1264 foreach (RuntimeJavaType iface
in tw.Interfaces)
1265 AddType1FieldAccessStubs(iface);
1267 tw = tw.BaseTypeWrapper;
1268 }
while (tw !=
null && !tw.IsPublic);
1271 void AddType2FieldAccessStubs()
1273 foreach (var fw
in wrapper.GetFields())
1274 if (wrapper.NeedsType2AccessStub(fw))
1275 GenerateAccessStub(fw,
false);
1278 void GenerateAccessStub(RuntimeJavaField fw,
bool type1)
1280 if (fw is RuntimeConstantJavaField cjf)
1283 Debug.Assert(type1);
1285 var attribs = fw.IsPublic ? FieldAttributes.Public : FieldAttributes.FamORAssem;
1286 attribs |= FieldAttributes.Static | FieldAttributes.Literal;
1290 var fb = typeBuilder.DefineField(fw.Name, fw.FieldTypeWrapper.TypeAsSignatureType,
null,
new Type[] { context.Resolver.ResolveRuntimeType(typeof(IKVM.Attributes.AccessStub).FullName).AsReflection() }, attribs);
1291 context.AttributeHelper.HideFromReflection(fb);
1292 fb.SetConstant(cjf.GetConstantValue());
1296 var propType = fw.FieldTypeWrapper.TypeAsPublicSignatureType;
1297 var modopt = wrapper.GetModOpt(fw.FieldTypeWrapper,
true);
1298 var pb = typeBuilder.DefineProperty(fw.Name, PropertyAttributes.None, propType,
null, modopt,
Type.EmptyTypes,
null,
null);
1300 context.AttributeHelper.HideFromReflection(pb);
1302 context.AttributeHelper.SetModifiers(pb, fw.Modifiers, fw.IsInternal);
1303 var attribs = fw.IsPublic ? MethodAttributes.Public : MethodAttributes.FamORAssem;
1304 attribs |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
1306 attribs |= MethodAttributes.Static;
1310 var modopt2 = ArrayUtil.Concat(modopt, context.Resolver.ResolveRuntimeType(typeof(
IKVM.
Attributes.
AccessStub).FullName).AsReflection());
1311 var getter = typeBuilder.DefineMethod(
"get_" + fw.Name, attribs, CallingConventions.Standard, propType,
null, modopt2,
Type.EmptyTypes,
null,
null);
1312 context.AttributeHelper.HideFromJava(getter);
1313 pb.SetGetMethod(getter);
1314 var ilgen = context.CodeEmitterFactory.Create(getter);
1316 ilgen.Emit(OpCodes.Ldarg_0);
1318 ilgen.Emit(OpCodes.Ret);
1321 if (!fw.IsFinal || (!fw.IsStatic && !type1))
1326 attribs &= ~MethodAttributes.MemberAccessMask;
1327 attribs |= MethodAttributes.Private;
1330 var setter = typeBuilder.DefineMethod(
"set_" + fw.Name, attribs, CallingConventions.Standard,
null,
null,
null,
new Type[] { propType },
null,
new Type[][] { modopt2 });
1331 context.AttributeHelper.HideFromJava(setter);
1332 pb.SetSetMethod(setter);
1333 ilgen = context.CodeEmitterFactory.Create(setter);
1334 ilgen.Emit(OpCodes.Ldarg_0);
1336 ilgen.Emit(OpCodes.Ldarg_1);
1339 if (propType != fw.FieldTypeWrapper.TypeAsSignatureType)
1340 ilgen.Emit(OpCodes.Castclass, fw.FieldTypeWrapper.TypeAsSignatureType);
1342 ilgen.Emit(OpCodes.Ret);
1348 void AddType1MethodAccessStubs(
ref int id)
1350 for (var tw = wrapper.BaseTypeWrapper; tw !=
null && !tw.IsPublic; tw = tw.BaseTypeWrapper)
1352 foreach (var mw
in tw.GetMethods())
1354 if ((mw.IsPublic || (mw.IsProtected && !wrapper.IsFinal))
1355 && (!mw.IsAbstract || wrapper.IsAbstract)
1356 && mw.Name != StringConstants.INIT
1357 && wrapper.GetMethod(mw.Name, mw.Signature,
true) == mw
1358 && ParametersAreAccessible(mw))
1360 GenerateAccessStub(
id, mw,
true,
true);
1361 if (!mw.IsStatic && !mw.IsFinal && !mw.IsAbstract && !wrapper.IsFinal)
1363 GenerateAccessStub(
id, mw,
false,
true);
1371 void AddType2MethodAccessStubs(
ref int id)
1373 foreach (var mw
in wrapper.GetMethods())
1375 if (mw.HasNonPublicTypeInSignature && (mw.IsPublic || (mw.IsProtected && !wrapper.IsFinal)) && ParametersAreAccessible(mw))
1377 GenerateAccessStub(
id, mw,
true,
false);
1378 if (!mw.IsStatic && !mw.IsFinal && !mw.IsAbstract && mw.Name != StringConstants.INIT && !wrapper.IsFinal)
1379 GenerateAccessStub(
id, mw,
false,
false);
1386 void GenerateAccessStub(
int id, RuntimeJavaMethod mw,
bool virt,
bool type1)
1388 Debug.Assert(!mw.HasCallerID);
1390 var stubattribs = mw.IsPublic && virt ? MethodAttributes.Public : MethodAttributes.FamORAssem;
1391 stubattribs |= MethodAttributes.HideBySig;
1393 stubattribs |= MethodAttributes.Static;
1395 var parameters = mw.GetParameters();
1396 var realParameterTypes =
new Type[parameters.Length];
1397 var parameterTypes =
new Type[parameters.Length];
1398 var modopt =
new Type[parameters.Length][];
1399 for (
int i = 0; i < parameters.Length; i++)
1401 realParameterTypes[i] = parameters[i].TypeAsSignatureType;
1402 parameterTypes[i] = parameters[i].TypeAsPublicSignatureType;
1403 modopt[i] = wrapper.GetModOpt(parameters[i],
true);
1406 var returnType = mw.ReturnType.TypeAsPublicSignatureType;
1407 var modoptReturnType = ArrayUtil.Concat(wrapper.GetModOpt(mw.ReturnType,
true), context.Resolver.ResolveRuntimeType(typeof(
IKVM.
Attributes.
AccessStub).FullName).AsReflection());
1410 if (mw.Name == StringConstants.INIT)
1413 stubattribs |= MethodAttributes.SpecialName | MethodAttributes.RTSpecialName;
1417 name = virt ? (mw.Modifiers &
Modifiers.Bridge) == 0 ? mw.Name : NamePrefix.Bridge + mw.Name : NamePrefix.NonVirtual + id;
1420 var mb = typeBuilder.DefineMethod(name, stubattribs, CallingConventions.Standard, returnType,
null, modoptReturnType, parameterTypes,
null, modopt);
1423 context.AttributeHelper.HideFromReflection(mb);
1424 context.AttributeHelper.SetNameSig(mb, NamePrefix.AccessStub +
id +
"|" + mw.Name, mw.Signature);
1428 context.AttributeHelper.HideFromJava(mb);
1431 context.AttributeHelper.SetNameSig(mb, mw.Name, mw.Signature);
1435 var ilgen = context.CodeEmitterFactory.Create(mb);
1438 ilgen.EmitLdarg(argpos++);
1440 for (
int i = 0; i < parameterTypes.Length; i++)
1442 ilgen.EmitLdarg(argpos++);
1445 if (parameterTypes[i] != realParameterTypes[i])
1446 ilgen.Emit(OpCodes.Castclass, realParameterTypes[i]);
1449 if (mw.IsStatic || !virt || mw.Name == StringConstants.INIT)
1452 mw.EmitCallvirt(ilgen);
1454 ilgen.Emit(OpCodes.Ret);
1458 bool ParametersAreAccessible(RuntimeJavaMethod mw)
1460 foreach (var tw
in mw.GetParameters())
1461 if (!tw.IsAccessibleFrom(wrapper))
1469 private void ImplementInterfaceMethodStubs(Dictionary<RuntimeJavaType, RuntimeJavaType> doneSet, RuntimeJavaType interfaceTypeWrapper,
bool baseClassInterface)
1471 Debug.Assert(interfaceTypeWrapper.IsInterface);
1474 if (doneSet.ContainsKey(interfaceTypeWrapper))
1478 doneSet.Add(interfaceTypeWrapper, interfaceTypeWrapper);
1479 foreach (RuntimeJavaMethod method
in interfaceTypeWrapper.GetMethods())
1481 if (!method.IsStatic && method.IsPublic && !method.IsDynamicOnly)
1483 ImplementInterfaceMethodStubImpl(method, baseClassInterface);
1486 RuntimeJavaType[] interfaces = interfaceTypeWrapper.Interfaces;
1487 for (
int i = 0; i < interfaces.Length; i++)
1489 ImplementInterfaceMethodStubs(doneSet, interfaces[i], baseClassInterface);
1493 void ImplementInterfaceMethodStubImpl(RuntimeJavaMethod ifmethod,
bool baseClassInterface)
1500 var mangledName = ifmethod.DeclaringType.Name +
"/" + ifmethod.Signature + ifmethod.Name;
1501 RuntimeJavaMethod mce =
null;
1503 var lookup = (RuntimeJavaType)wrapper;
1504 while (lookup !=
null)
1506 mce = lookup.GetMethod(ifmethod.Name, ifmethod.Signature,
true);
1507 if (mce ==
null || !mce.IsStatic)
1510 lookup = mce.DeclaringType.BaseTypeWrapper;
1515 Debug.Assert(!mce.HasCallerID);
1516 if (mce.DeclaringType != wrapper)
1520 if (mce.ReturnType != ifmethod.ReturnType && !mce.ReturnType.IsUnloadable && !ifmethod.ReturnType.IsUnloadable)
1523 var mceparams = mce.GetParameters();
1524 var ifparams = ifmethod.GetParameters();
1525 for (
int i = 0; i < mceparams.Length; i++)
1527 if (mceparams[i] != ifparams[i] && !mceparams[i].IsUnloadable && !ifparams[i].IsUnloadable)
1536 var mb = DefineInterfaceStubMethod(mangledName, ifmethod);
1537 context.AttributeHelper.HideFromJava(mb);
1538 var ilgen = context.CodeEmitterFactory.Create(mb);
1539 ilgen.EmitThrow(
"java.lang.LinkageError", wrapper.Name +
"." + ifmethod.Name + ifmethod.Signature);
1541 typeBuilder.DefineMethodOverride(mb, (
MethodInfo)ifmethod.GetMethod());
1546 if (!mce.IsPublic && !mce.IsInternal)
1553 var mb = DefineInterfaceStubMethod(NamePrefix.Incomplete + mangledName, ifmethod);
1554 context.AttributeHelper.HideFromJava(mb);
1555 var ilgen = context.CodeEmitterFactory.Create(mb);
1556 ilgen.EmitThrow(
"java.lang.IllegalAccessError", wrapper.Name +
"." + ifmethod.Name + ifmethod.Signature);
1558 typeBuilder.DefineMethodOverride(mb, (
MethodInfo)ifmethod.GetMethod());
1559 wrapper.SetHasIncompleteInterfaceImplementation();
1561 else if (mce.GetMethod() ==
null || mce.RealName != ifmethod.RealName || mce.IsInternal || !ReflectUtil.IsSameAssembly(mce.DeclaringType.TypeAsTBD, typeBuilder) || CheckRequireOverrideStub(mce, ifmethod))
1566 wrapper.GenerateOverrideStub(typeBuilder, ifmethod,
null, mce);
1568 else if (baseClassInterface && mce.DeclaringType == wrapper)
1570 typeBuilder.DefineMethodOverride((
MethodInfo)mce.GetMethod(), (
MethodInfo)ifmethod.GetMethod());
1575 if (!wrapper.IsAbstract || (!baseClassInterface && wrapper.GetMethod(ifmethod.Name, ifmethod.Signature,
false) !=
null))
1579 var mb = DefineInterfaceStubMethod(NamePrefix.Incomplete + mangledName, ifmethod);
1580 context.AttributeHelper.HideFromJava(mb);
1581 var ilgen = context.CodeEmitterFactory.Create(mb);
1582 ilgen.EmitThrow(
"java.lang.AbstractMethodError", wrapper.Name +
"." + ifmethod.Name + ifmethod.Signature);
1584 typeBuilder.DefineMethodOverride(mb, (
MethodInfo)ifmethod.GetMethod());
1585 wrapper.SetHasIncompleteInterfaceImplementation();
1586 wrapper.EmitLevel4Warning(
HardError.AbstractMethodError, wrapper.Name +
"." + ifmethod.Name + ifmethod.Signature);
1591 MethodBuilder DefineInterfaceStubMethod(
string name, RuntimeJavaMethod mw)
1593 return mw.GetDefineMethodHelper().DefineMethod(wrapper, typeBuilder, name, MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Private | MethodAttributes.Virtual | MethodAttributes.Final);
1596#if FIRST_PASS == false && IMPORTER == false
1598 internal static class JniProxyBuilder
1601 readonly
static ModuleBuilder mod;
1607 static JniProxyBuilder()
1609 mod = DynamicClassLoader.CreateJniProxyModuleBuilder();
1610 var cab =
new CustomAttributeBuilder(JVM.Context.Resolver.ResolveRuntimeType(typeof(
JavaModuleAttribute).FullName).GetConstructor([]).AsReflection(),
new object[0]);
1611 mod.SetCustomAttribute(cab);
1614 internal static void Generate(RuntimeByteCodeJavaType.FinishContext context, CodeEmitter ilGenerator, RuntimeByteCodeJavaType wrapper, RuntimeJavaMethod mw, TypeBuilder typeBuilder, ClassFile classFile, ClassFile.Method m, RuntimeJavaType[] args)
1616 TypeBuilder tb = mod.DefineType(
"__<jni>" +
System.Threading.Interlocked.Increment(
ref count), TypeAttributes.Public | TypeAttributes.Class);
1617 int instance = m.IsStatic ? 0 : 1;
1618 Type[] argTypes =
new Type[args.Length + instance + 1];
1621 argTypes[0] = typeof(
object);
1623 for (
int i = 0; i < args.Length; i++)
1627 argTypes[i + instance] = !args[i].IsUnloadable && (args[i].IsPrimitive || args[i].IsGhost || args[i].IsNonPrimitiveValueType) ? args[i].TypeAsSignatureType : typeof(
object);
1629 argTypes[argTypes.Length - 1] = context.context.JavaBase.TypeOfIkvmInternalCallerID.TypeAsSignatureType;
1630 Type retType = !mw.ReturnType.IsUnloadable && (mw.ReturnType.IsPrimitive || mw.ReturnType.IsGhost || mw.ReturnType.IsNonPrimitiveValueType) ? mw.ReturnType.TypeAsSignatureType : typeof(
object);
1631 MethodBuilder mb = tb.DefineMethod(
"method", MethodAttributes.Public | MethodAttributes.Static, retType, argTypes);
1632 context.context.AttributeHelper.HideFromJava(mb);
1633 CodeEmitter ilgen = context.context.CodeEmitterFactory.Create(mb);
1634 new JniBuilder(context.context).Generate(context, ilgen, wrapper, mw, tb, classFile, m, args,
true);
1637 for (
int i = 0; i < argTypes.Length - 1; i++)
1639 ilGenerator.EmitLdarg(i);
1641 context.EmitCallerID(ilGenerator, m.IsLambdaFormCompiled);
1642 ilGenerator.Emit(OpCodes.Call, mb);
1643 if (!mw.ReturnType.IsUnloadable && !mw.ReturnType.IsPrimitive && !mw.ReturnType.IsGhost && !mw.ReturnType.IsNonPrimitiveValueType)
1645 ilGenerator.Emit(OpCodes.Castclass, mw.ReturnType.TypeAsSignatureType);
1647 ilGenerator.Emit(OpCodes.Ret);
1655 readonly RuntimeContext context;
1661 public JniBuilder(RuntimeContext context)
1663 this.context = context ??
throw new ArgumentNullException(nameof(context));
1666 Type LocalRefStructType => context.Resolver.ResolveRuntimeType(
"IKVM.Runtime.JNI.JNIFrame").AsReflection();
1668 MethodInfo JniFuncPtrMethod => LocalRefStructType.GetMethod(
"GetFuncPtr");
1670 MethodInfo EnterLocalRefStructMethod => LocalRefStructType.GetMethod(
"Enter");
1672 MethodInfo LeaveLocalRefStructMethod => LocalRefStructType.GetMethod(
"Leave");
1674 MethodInfo MakeLocalRefMethod => LocalRefStructType.GetMethod(
"MakeLocalRef");
1676 MethodInfo UnwrapLocalRefMethod => LocalRefStructType.GetMethod(
"UnwrapLocalRef");
1678 MethodInfo WriteLineMethod => context.Resolver.ResolveCoreType(typeof(Console).FullName).AsReflection().GetMethod(
"WriteLine", [context.Types.Object]);
1680 MethodInfo MonitorEnterMethod => context.Resolver.ResolveCoreType(typeof(
System.Threading.Monitor).FullName).AsReflection().GetMethod(
"Enter", [context.Types.Object]);
1682 MethodInfo MonitorExitMethod => context.Resolver.ResolveCoreType(typeof(
System.Threading.Monitor).FullName).AsReflection().GetMethod(
"Exit", [context.Types.Object]);
1684 internal void Generate(RuntimeByteCodeJavaType.FinishContext context, CodeEmitter ilGenerator, RuntimeByteCodeJavaType wrapper, RuntimeJavaMethod mw, TypeBuilder typeBuilder, ClassFile classFile, ClassFile.Method m, RuntimeJavaType[] args,
bool thruProxy)
1686 CodeEmitterLocal syncObject =
null;
1687 if (m.IsSynchronized && m.IsStatic)
1689 wrapper.EmitClassLiteral(ilGenerator);
1690 ilGenerator.Emit(OpCodes.Dup);
1691 syncObject = ilGenerator.DeclareLocal(context.context.Types.Object);
1692 ilGenerator.Emit(OpCodes.Stloc, syncObject);
1693 ilGenerator.Emit(OpCodes.Call, MonitorEnterMethod);
1694 ilGenerator.BeginExceptionBlock();
1697 var sig = m.Signature.Replace(
'.',
'/');
1699 var methodPtr = typeBuilder.DefineField(
"__<jniptr>" + m.Name + sig, context.context.Types.IntPtr, FieldAttributes.Static | FieldAttributes.PrivateScope);
1700 var localRefStruct = ilGenerator.DeclareLocal(LocalRefStructType);
1701 ilGenerator.Emit(OpCodes.Ldloca, localRefStruct);
1702 ilGenerator.Emit(OpCodes.Initobj, LocalRefStructType);
1703 ilGenerator.Emit(OpCodes.Ldsfld, methodPtr);
1704 var oklabel = ilGenerator.DefineLabel();
1705 ilGenerator.EmitBrtrue(oklabel);
1708 ilGenerator.EmitLdarg(args.Length + (mw.IsStatic ? 0 : 1));
1710 context.EmitCallerID(ilGenerator, m.IsLambdaFormCompiled);
1711 ilGenerator.Emit(OpCodes.Ldstr, classFile.Name.Replace(
'.',
'/'));
1712 ilGenerator.Emit(OpCodes.Ldstr, m.Name);
1713 ilGenerator.Emit(OpCodes.Ldstr, sig);
1714 ilGenerator.Emit(OpCodes.Call, JniFuncPtrMethod);
1715 ilGenerator.Emit(OpCodes.Stsfld, methodPtr);
1716 ilGenerator.MarkLabel(oklabel);
1717 ilGenerator.Emit(OpCodes.Ldloca, localRefStruct);
1719 ilGenerator.EmitLdarg(args.Length + (mw.IsStatic ? 0 : 1));
1721 context.EmitCallerID(ilGenerator, m.IsLambdaFormCompiled);
1722 ilGenerator.Emit(OpCodes.Call, EnterLocalRefStructMethod);
1724 var jnienv = ilGenerator.DeclareLocal(context.context.Types.IntPtr);
1725 ilGenerator.Emit(OpCodes.Stloc, jnienv);
1727 ilGenerator.BeginExceptionBlock();
1728 var retTypeWrapper = mw.ReturnType;
1729 if (retTypeWrapper.IsUnloadable || !retTypeWrapper.IsPrimitive)
1732 ilGenerator.Emit(OpCodes.Ldloca, localRefStruct);
1735 ilGenerator.Emit(OpCodes.Ldloc, jnienv);
1737 var modargs =
new Type[args.Length + 2];
1738 modargs[0] = context.context.Types.IntPtr;
1739 modargs[1] = context.context.Types.IntPtr;
1740 for (
int i = 0; i < args.Length; i++)
1741 modargs[i + 2] = args[i].TypeAsSignatureType;
1745 ilGenerator.Emit(OpCodes.Ldloca, localRefStruct);
1746 ilGenerator.Emit(OpCodes.Ldarg_0);
1747 ilGenerator.Emit(OpCodes.Call, MakeLocalRefMethod);
1752 ilGenerator.Emit(OpCodes.Ldloca, localRefStruct);
1753 wrapper.EmitClassLiteral(ilGenerator);
1754 ilGenerator.Emit(OpCodes.Call, MakeLocalRefMethod);
1757 for (
int j = 0; j < args.Length; j++)
1759 if (args[j].IsUnloadable || !args[j].IsPrimitive)
1761 ilGenerator.Emit(OpCodes.Ldloca, localRefStruct);
1762 if (!args[j].IsUnloadable && args[j].IsNonPrimitiveValueType)
1764 ilGenerator.EmitLdarg(j + add);
1765 args[j].EmitBox(ilGenerator);
1767 else if (!args[j].IsUnloadable && args[j].IsGhost)
1769 ilGenerator.EmitLdarga(j + add);
1770 ilGenerator.Emit(OpCodes.Ldfld, args[j].GhostRefField);
1774 ilGenerator.EmitLdarg(j + add);
1776 ilGenerator.Emit(OpCodes.Call, MakeLocalRefMethod);
1777 modargs[j + 2] = context.context.Types.IntPtr;
1781 ilGenerator.EmitLdarg(j + add);
1785 ilGenerator.Emit(OpCodes.Ldsfld, methodPtr);
1788 if (retTypeWrapper == context.Context.PrimitiveJavaTypeFactory.BOOLEAN)
1789 realRetType = context.Context.Types.Byte;
1790 else if (retTypeWrapper.IsPrimitive)
1791 realRetType = retTypeWrapper.TypeAsSignatureType;
1793 realRetType = context.Context.Types.IntPtr;
1794 ilGenerator.EmitCalli(OpCodes.Calli,
System.
Runtime.InteropServices.CallingConvention.StdCall, realRetType, modargs);
1796 CodeEmitterLocal retValue =
null;
1797 if (retTypeWrapper != context.Context.PrimitiveJavaTypeFactory.VOID)
1799 if (retTypeWrapper.IsUnloadable)
1801 ilGenerator.Emit(OpCodes.Call, UnwrapLocalRefMethod);
1803 else if (!retTypeWrapper.IsPrimitive)
1805 ilGenerator.Emit(OpCodes.Call, UnwrapLocalRefMethod);
1806 if (retTypeWrapper.IsNonPrimitiveValueType)
1808 retTypeWrapper.EmitUnbox(ilGenerator);
1810 else if (retTypeWrapper.IsGhost)
1812 var ghost = ilGenerator.DeclareLocal(retTypeWrapper.TypeAsSignatureType);
1813 var obj = ilGenerator.DeclareLocal(context.Context.Types.Object);
1814 ilGenerator.Emit(OpCodes.Stloc, obj);
1815 ilGenerator.Emit(OpCodes.Ldloca, ghost);
1816 ilGenerator.Emit(OpCodes.Ldloc, obj);
1817 ilGenerator.Emit(OpCodes.Stfld, retTypeWrapper.GhostRefField);
1818 ilGenerator.Emit(OpCodes.Ldloc, ghost);
1822 ilGenerator.Emit(OpCodes.Castclass, retTypeWrapper.TypeAsTBD);
1826 retValue = ilGenerator.DeclareLocal(retTypeWrapper.TypeAsSignatureType);
1827 ilGenerator.Emit(OpCodes.Stloc, retValue);
1830 var retLabel = ilGenerator.DefineLabel();
1831 ilGenerator.EmitLeave(retLabel);
1832 ilGenerator.BeginCatchBlock(context.context.Types.Object);
1833 ilGenerator.Emit(OpCodes.Ldstr,
"*** exception in native code ***");
1834 ilGenerator.Emit(OpCodes.Call, WriteLineMethod);
1835 ilGenerator.Emit(OpCodes.Call, WriteLineMethod);
1836 ilGenerator.Emit(OpCodes.Rethrow);
1837 ilGenerator.BeginFinallyBlock();
1838 ilGenerator.Emit(OpCodes.Ldloca, localRefStruct);
1839 ilGenerator.Emit(OpCodes.Call, LeaveLocalRefStructMethod);
1840 ilGenerator.Emit(OpCodes.Endfinally);
1841 ilGenerator.EndExceptionBlock();
1842 if (m.IsSynchronized && m.IsStatic)
1844 ilGenerator.BeginFinallyBlock();
1845 ilGenerator.Emit(OpCodes.Ldloc, syncObject);
1846 ilGenerator.Emit(OpCodes.Call, MonitorExitMethod);
1847 ilGenerator.Emit(OpCodes.Endfinally);
1848 ilGenerator.EndExceptionBlock();
1850 ilGenerator.MarkLabel(retLabel);
1851 if (retTypeWrapper != context.Context.PrimitiveJavaTypeFactory.VOID)
1852 ilGenerator.Emit(OpCodes.Ldloc, retValue);
1854 ilGenerator.Emit(OpCodes.Ret);
1860 void EmitCallerIDStub(RuntimeJavaMethod mw,
string[] parameterNames)
1863 var parameters = mw.GetParameters();
1864 var parameterTypes =
new Type[parameters.Length];
1865 for (
int i = 0; i < parameterTypes.Length; i++)
1866 parameterTypes[i] = parameters[i].TypeAsSignatureType;
1868 var attribs = MethodAttributes.HideBySig;
1869 int argcount = parameterTypes.Length;
1872 attribs |= MethodAttributes.Static;
1880 attribs |= MethodAttributes.Public;
1882 else if (mw.IsProtected)
1884 attribs |= MethodAttributes.FamORAssem;
1886 else if (mw.IsPrivate)
1888 attribs |= MethodAttributes.Private;
1892 attribs |= MethodAttributes.Assembly;
1895 var mb = typeBuilder.DefineMethod(mw.Name, attribs, mw.ReturnType.TypeAsSignatureType, parameterTypes);
1896 context.AttributeHelper.HideFromJava(mb);
1897 mb.SetImplementationFlags(MethodImplAttributes.NoInlining);
1899 var ilgen = context.CodeEmitterFactory.Create(mb);
1900 for (
int i = 0; i < argcount; i++)
1902 if (parameterNames !=
null && (mw.IsStatic || i > 0))
1904 var pb = mb.DefineParameter(mw.IsStatic ? i + 1 : i, ParameterAttributes.None, parameterNames[mw.IsStatic ? i : i - 1]);
1905 if (i == argcount - 1 && (mw.Modifiers &
Modifiers.VarArgs) != 0)
1906 context.AttributeHelper.SetParamArrayAttribute(pb);
1911 ilgen.Emit(OpCodes.Ldc_I4_1);
1912 ilgen.Emit(OpCodes.Ldc_I4_0);
1913 ilgen.Emit(OpCodes.Newobj, context.Resolver.ResolveCoreType(typeof(StackFrame).FullName).AsReflection().GetConstructor(
new Type[] { context.Types.Int32, context.Types.Boolean }));
1914 var callerID = context.JavaBase.TypeOfIkvmInternalCallerID.GetMethod(
"create",
"(Lcli.System.Diagnostics.StackFrame;)Likvm.internal.CallerID;",
false);
1916 callerID.EmitCall(ilgen);
1920 mw.EmitCallvirt(ilgen);
1921 ilgen.Emit(OpCodes.Ret);
1927 void ImplementInterfaces(RuntimeJavaType[] interfaces, List<RuntimeJavaType> interfaceList)
1929 foreach (var iface
in interfaces)
1931 if (!interfaceList.Contains(iface))
1933 interfaceList.Add(iface);
1934 if (!iface.IsAccessibleFrom(wrapper))
1939 typeBuilder.AddInterfaceImplementation(iface.TypeAsBaseType);
1941 if (!wrapper.IsInterface)
1944 if (iface.ClassLoader == context.JavaBase.TypeOfJavaLangObject.ClassLoader)
1946 if (iface.Name ==
"java.lang.Iterable" && !wrapper.ImplementsInterface(context.ClassLoaderFactory.GetJavaTypeFromType(context.Resolver.ResolveCoreType(typeof(
System.Collections.IEnumerable).FullName).AsReflection())))
1948 var enumeratorType = context.ClassLoaderFactory.GetBootstrapClassLoader().TryLoadClassByName(
"ikvm.lang.IterableEnumerator");
1949 if (enumeratorType !=
null)
1951 typeBuilder.AddInterfaceImplementation(context.Resolver.ResolveCoreType(typeof(
System.Collections.IEnumerable).FullName).AsReflection());
1953 var mb = typeBuilder.DefineMethod(
"System.Collections.IEnumerable.GetEnumerator", MethodAttributes.Private | MethodAttributes.Virtual | MethodAttributes.NewSlot | MethodAttributes.Final | MethodAttributes.SpecialName, context.Resolver.ResolveCoreType(typeof(
System.Collections.IEnumerator).FullName).AsReflection(),
Type.EmptyTypes);
1954 context.AttributeHelper.HideFromJava(mb);
1955 typeBuilder.DefineMethodOverride(mb, context.Resolver.ResolveCoreType(typeof(
System.Collections.IEnumerable).FullName).GetMethod(
"GetEnumerator").AsReflection());
1956 var ilgen = context.CodeEmitterFactory.Create(mb);
1957 ilgen.Emit(OpCodes.Ldarg_0);
1958 var mw = enumeratorType.GetMethod(
"<init>",
"(Ljava.lang.Iterable;)V",
false);
1960 mw.EmitNewobj(ilgen);
1961 ilgen.Emit(OpCodes.Ret);
1967 if (iface.IsGhost && wrapper.IsPublic)
1969 var mb = typeBuilder.DefineMethod(
"op_Implicit", MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.Static | MethodAttributes.SpecialName, iface.TypeAsSignatureType,
new Type[] { wrapper.TypeAsSignatureType });
1970 context.AttributeHelper.HideFromJava(mb);
1971 var ilgen = context.CodeEmitterFactory.Create(mb);
1972 var local = ilgen.DeclareLocal(iface.TypeAsSignatureType);
1973 ilgen.Emit(OpCodes.Ldloca, local);
1974 ilgen.Emit(OpCodes.Ldarg_0);
1975 ilgen.Emit(OpCodes.Stfld, iface.GhostRefField);
1976 ilgen.Emit(OpCodes.Ldloca, local);
1977 ilgen.Emit(OpCodes.Ldobj, iface.TypeAsSignatureType);
1978 ilgen.Emit(OpCodes.Ret);
1985 ImplementInterfaces(iface.Interfaces, interfaceList);
1990 void AddUnsupportedAbstractMethods()
1992 foreach (var mb
in wrapper.BaseTypeWrapper.TypeAsBaseType.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
1993 if (RuntimeManagedJavaType.IsUnsupportedAbstractMethod(mb))
1994 GenerateUnsupportedAbstractMethodStub(mb);
1996 var h =
new Dictionary<MethodBase, MethodBase>();
1997 var tw = (RuntimeJavaType)wrapper;
2000 foreach (var iface
in tw.Interfaces)
2002 foreach (var mb
in iface.TypeAsBaseType.GetMethods(BindingFlags.Public | BindingFlags.Instance))
2004 if (!h.ContainsKey(mb))
2007 if (RuntimeManagedJavaType.IsUnsupportedAbstractMethod(mb))
2008 GenerateUnsupportedAbstractMethodStub(mb);
2013 tw = tw.BaseTypeWrapper;
2017 void GenerateUnsupportedAbstractMethodStub(
MethodBase mb)
2019 var parameters = mb.GetParameters();
2020 var parameterTypes =
new Type[parameters.Length];
2021 for (
int i = 0; i < parameters.Length; i++)
2022 parameterTypes[i] = parameters[i].ParameterType;
2024 var attr = MethodAttributes.NewSlot | MethodAttributes.Virtual | MethodAttributes.Private;
2025 var m = typeBuilder.DefineMethod(
"__<unsupported>" + mb.DeclaringType.FullName +
"/" + mb.Name, attr, ((
MethodInfo)mb).ReturnType, parameterTypes);
2026 if (mb.IsGenericMethodDefinition)
2027 CopyGenericArguments(mb, m);
2029 var ilgen = context.CodeEmitterFactory.Create(m);
2030 ilgen.EmitThrow(
"java.lang.AbstractMethodError",
"Method " + mb.DeclaringType.FullName +
"." + mb.Name +
" is unsupported by IKVM.");
2032 typeBuilder.DefineMethodOverride(m, (
MethodInfo)mb);
2035 void CopyGenericArguments(
MethodBase mi, MethodBuilder mb)
2037 var genericParameters = mi.GetGenericArguments();
2038 var genParamNames =
new string[genericParameters.Length];
2039 for (
int i = 0; i < genParamNames.Length; i++)
2040 genParamNames[i] = genericParameters[i].
Name;
2042 var genParamBuilders = mb.DefineGenericParameters(genParamNames);
2043 for (
int i = 0; i < genParamBuilders.Length; i++)
2047 if (genericParameters[i].BaseType != context.Types.Object)
2048 genParamBuilders[i].SetBaseTypeConstraint(genericParameters[i].BaseType);
2050 genParamBuilders[i].SetGenericParameterAttributes(genericParameters[i].GenericParameterAttributes);
2054 void CompileConstructorBody(FinishContext context, CodeEmitter ilGenerator,
int methodIndex)
2056 var methods = wrapper.GetMethods();
2057 var m = classFile.Methods[methodIndex];
2061 if (wrapper.EmitMapXmlMethodPrologueAndOrBody(ilGenerator, classFile, m))
2063 ilGenerator.DoEmit();
2067 var nonLeaf =
false;
2068 Compiler.Compile(context, host, wrapper, methods[methodIndex], classFile, m, ilGenerator,
ref nonLeaf);
2069 ilGenerator.DoEmit();
2071 ilGenerator.EmitLineNumberTable((MethodBuilder)methods[methodIndex].GetMethod());
2073 var linenumbers = ilGenerator.GetLineNumberTable();
2074 if (linenumbers !=
null)
2076 if (wrapper.lineNumberTables ==
null)
2077 wrapper.lineNumberTables =
new byte[methods.Length][];
2079 wrapper.lineNumberTables[methodIndex] = linenumbers;
2084 static bool IsCompatibleArgList(RuntimeJavaType[] caller, RuntimeJavaType[] callee)
2086 if (caller.Length == callee.Length)
2088 for (
int i = 0; i < caller.Length; i++)
2090 if (caller[i].IsUnloadable || callee[i].IsUnloadable)
2092 if (!caller[i].IsAssignableTo(callee[i]))
2102 void EmitCallerIDInitialization(CodeEmitter ilGenerator,
FieldInfo callerIDField)
2104 var tw = context.JavaBase.TypeOfIkvmInternalCallerID;
2105 if (tw.InternalsVisibleTo(wrapper))
2107 var create = tw.GetMethod(
"create",
"(Lcli.System.RuntimeTypeHandle;)Likvm.internal.CallerID;",
false);
2108 ilGenerator.Emit(OpCodes.Ldtoken,
this.typeBuilder);
2110 create.EmitCall(ilGenerator);
2114 RegisterNestedTypeBuilder(EmitCreateCallerID(context, typeBuilder, ilGenerator));
2117 ilGenerator.Emit(OpCodes.Stsfld, callerIDField);
2120 internal static TypeBuilder EmitCreateCallerID(RuntimeContext context, TypeBuilder typeBuilder, CodeEmitter ilGenerator)
2122 var tw = context.JavaBase.TypeOfIkvmInternalCallerID;
2123 var typeCallerID = typeBuilder.DefineNestedType(NestedTypeName.CallerID, TypeAttributes.Sealed | TypeAttributes.NestedPrivate, tw.TypeAsBaseType);
2124 var cb = ReflectUtil.DefineConstructor(typeCallerID, MethodAttributes.Assembly,
null);
2125 var ctorIlgen = context.CodeEmitterFactory.Create(cb);
2126 ctorIlgen.Emit(OpCodes.Ldarg_0);
2127 var mw = tw.GetMethod(
"<init>",
"()V",
false);
2129 mw.EmitCall(ctorIlgen);
2130 ctorIlgen.Emit(OpCodes.Ret);
2132 ilGenerator.Emit(OpCodes.Newobj, cb);
2133 return typeCallerID;
2136 void EmitConstantValueInitialization(RuntimeJavaField[] fields, CodeEmitter ilGenerator)
2138 ClassFile.Field[] flds = classFile.Fields;
2139 for (
int i = 0; i < flds.Length; i++)
2141 ClassFile.Field f = flds[i];
2142 if (f.IsStatic && !f.IsFinal)
2144 object constant = f.ConstantValue;
2145 if (constant !=
null)
2147 if (constant is
int)
2149 ilGenerator.EmitLdc_I4((
int)constant);
2151 else if (constant is
bool)
2153 ilGenerator.EmitLdc_I4((
bool)constant ? 1 : 0);
2155 else if (constant is
byte)
2157 ilGenerator.EmitLdc_I4((
byte)constant);
2159 else if (constant is
char)
2161 ilGenerator.EmitLdc_I4((
char)constant);
2163 else if (constant is
short)
2165 ilGenerator.EmitLdc_I4((
short)constant);
2167 else if (constant is
long)
2169 ilGenerator.EmitLdc_I8((
long)constant);
2171 else if (constant is
double)
2173 ilGenerator.EmitLdc_R8((
double)constant);
2175 else if (constant is
float)
2177 ilGenerator.EmitLdc_R4((
float)constant);
2179 else if (constant is
string)
2181 ilGenerator.Emit(OpCodes.Ldstr, (
string)constant);
2185 throw new InvalidOperationException();
2187 fields[i].EmitSet(ilGenerator);
2193 internal MethodBuilder DefineThreadLocalType()
2195 var threadLocal = context.ClassLoaderFactory.LoadClassCritical(
"ikvm.internal.IntrinsicThreadLocal");
2196 int id = nestedTypeBuilders ==
null ? 0 : nestedTypeBuilders.Count;
2197 var tb = typeBuilder.DefineNestedType(NestedTypeName.ThreadLocal +
id, TypeAttributes.NestedPrivate | TypeAttributes.Sealed, threadLocal.TypeAsBaseType);
2198 var fb = tb.DefineField(
"field", context.Types.Object, FieldAttributes.Private | FieldAttributes.Static);
2199 fb.SetCustomAttribute(
new CustomAttributeBuilder(context.Resolver.ResolveCoreType(typeof(ThreadStaticAttribute).FullName).GetConstructor([]).AsReflection(),
new object[0]));
2201 var mbGet = tb.DefineMethod(
"get", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.Final, context.Types.Object,
Type.EmptyTypes);
2202 var ilgen = mbGet.GetILGenerator();
2203 ilgen.Emit(OpCodes.Ldsfld, fb);
2204 ilgen.Emit(OpCodes.Ret);
2206 var mbSet = tb.DefineMethod(
"set", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.Final,
null, [context.Types.Object]);
2207 ilgen = mbSet.GetILGenerator();
2208 ilgen.Emit(OpCodes.Ldarg_1);
2209 ilgen.Emit(OpCodes.Stsfld, fb);
2210 ilgen.Emit(OpCodes.Ret);
2212 var cb = ReflectUtil.DefineConstructor(tb, MethodAttributes.Assembly,
Type.EmptyTypes);
2213 var ctorilgen = context.CodeEmitterFactory.Create(cb);
2214 ctorilgen.Emit(OpCodes.Ldarg_0);
2215 var basector = threadLocal.GetMethod(
"<init>",
"()V",
false);
2217 basector.EmitCall(ctorilgen);
2218 ctorilgen.Emit(OpCodes.Ret);
2221 RegisterNestedTypeBuilder(tb);
2225 internal MethodBuilder GetAtomicReferenceFieldUpdater(RuntimeJavaField field)
2227 arfuMap ??=
new Dictionary<RuntimeJavaField, MethodBuilder>();
2229 if (!arfuMap.TryGetValue(field, out var cb))
2231 RuntimeJavaType arfuTypeWrapper = context.ClassLoaderFactory.LoadClassCritical(
"ikvm.internal.IntrinsicAtomicReferenceFieldUpdater");
2232 TypeBuilder tb = typeBuilder.DefineNestedType(NestedTypeName.AtomicReferenceFieldUpdater + arfuMap.Count, TypeAttributes.NestedPrivate | TypeAttributes.Sealed, arfuTypeWrapper.TypeAsBaseType);
2233 AtomicReferenceFieldUpdaterEmitter.EmitImpl(context, tb, field.GetField());
2234 cb = ReflectUtil.DefineConstructor(tb, MethodAttributes.Assembly,
Type.EmptyTypes);
2235 arfuMap.Add(field, cb);
2236 CodeEmitter ctorilgen = context.CodeEmitterFactory.Create(cb);
2237 ctorilgen.Emit(OpCodes.Ldarg_0);
2238 RuntimeJavaMethod basector = arfuTypeWrapper.GetMethod(
"<init>",
"()V",
false);
2240 basector.EmitCall(ctorilgen);
2241 ctorilgen.Emit(OpCodes.Ret);
2243 RegisterNestedTypeBuilder(tb);
2248 internal TypeBuilder DefineIndyCallSiteType()
2250 int id = nestedTypeBuilders ==
null ? 0 : nestedTypeBuilders.Count;
2251 var tb = typeBuilder.DefineNestedType(NestedTypeName.IndyCallSite +
id, TypeAttributes.NestedPrivate | TypeAttributes.Abstract | TypeAttributes.Sealed | TypeAttributes.BeforeFieldInit);
2252 RegisterNestedTypeBuilder(tb);
2256 internal TypeBuilder DefineMethodHandleConstantType(MethodHandleConstantHandle handle)
2258 var tb = typeBuilder.DefineNestedType(NestedTypeName.MethodHandleConstant + handle.Slot, TypeAttributes.NestedPrivate | TypeAttributes.Sealed | TypeAttributes.Abstract | TypeAttributes.BeforeFieldInit); ;
2259 RegisterNestedTypeBuilder(tb);
2263 internal TypeBuilder DefineMethodTypeConstantType(MethodTypeConstantHandle handle)
2265 var tb = typeBuilder.DefineNestedType(NestedTypeName.MethodTypeConstant + handle.Slot, TypeAttributes.NestedPrivate | TypeAttributes.Sealed | TypeAttributes.Abstract | TypeAttributes.BeforeFieldInit);
2266 RegisterNestedTypeBuilder(tb);
2271 internal TypeBuilder DefineAnonymousClass()
2273 int id = nestedTypeBuilders ==
null ? 0 : nestedTypeBuilders.Count;
2274 var tb = typeBuilder.DefineNestedType(NestedTypeName.IntrinsifiedAnonymousClass +
id, TypeAttributes.NestedPrivate | TypeAttributes.Sealed | TypeAttributes.SpecialName | TypeAttributes.BeforeFieldInit);
2275 RegisterNestedTypeBuilder(tb);
2279 MethodBuilder DefineHelperMethod(
string name,
Type returnType,
Type[] parameterTypes)
2281 return typeBuilder.DefineMethod(name, MethodAttributes.PrivateScope | MethodAttributes.Static, returnType, parameterTypes);
2284 internal MethodBuilder DefineMethodHandleDispatchStub(
Type returnType,
Type[] parameterTypes)
2286 return DefineHelperMethod(
"__<>MHC", returnType, parameterTypes);
2289 internal FieldBuilder DefineMethodHandleInvokeCacheField(
Type fieldType)
2291 return typeBuilder.DefineField(
"__<>invokeCache", fieldType, FieldAttributes.Static | FieldAttributes.PrivateScope);
2294 internal FieldBuilder DefineDynamicMethodHandleCacheField()
2296 return typeBuilder.DefineField(
"__<>dynamicMethodHandleCache", context.JavaBase.TypeOfJavaLangInvokeMethodHandle.TypeAsSignatureType, FieldAttributes.Static | FieldAttributes.PrivateScope);
2299 internal FieldBuilder DefineDynamicMethodTypeCacheField()
2301 return typeBuilder.DefineField(
"__<>dynamicMethodTypeCache", context.JavaBase.TypeOfJavaLangInvokeMethodType.TypeAsSignatureType, FieldAttributes.Static | FieldAttributes.PrivateScope);
2304 internal MethodBuilder DefineDelegateInvokeErrorStub(
Type returnType,
Type[] parameterTypes)
2306 return DefineHelperMethod(
"__<>", returnType, parameterTypes);
2309 internal MethodInfo GetInvokeSpecialStub(RuntimeJavaMethod method)
2311 invokespecialstubcache ??=
new Dictionary<MethodKey, MethodInfo>();
2313 var key =
new MethodKey(method.DeclaringType.Name, method.Name, method.Signature);
2315 if (!invokespecialstubcache.TryGetValue(key, out var mi))
2317 var dmh = method.GetDefineMethodHelper();
2318 var stub = dmh.DefineMethod(wrapper, typeBuilder,
"__<>", MethodAttributes.PrivateScope);
2319 var ilgen = context.CodeEmitterFactory.Create(stub);
2320 ilgen.Emit(OpCodes.Ldarg_0);
2321 for (
int i = 1; i <= dmh.ParameterCount; i++)
2323 method.EmitCall(ilgen);
2324 ilgen.Emit(OpCodes.Ret);
2326 invokespecialstubcache[key] = stub;
2335 internal void EmitLiveObjectLoad(CodeEmitter ilgen,
object value)
2337 liveObjects ??=
new List<object>();
2339 ilgen.Emit(OpCodes.Ldsfld, fi);
2340 ilgen.EmitLdc_I4(liveObjects.Count);
2341 ilgen.Emit(OpCodes.Ldelem_Ref);
2342 liveObjects.Add(value);
IKVM.Reflection.Type Type
IKVM.Reflection.ConstructorInfo ConstructorInfo
IKVM.Reflection.FieldInfo FieldInfo
IKVM.Reflection.MethodInfo MethodInfo
IKVM.Reflection.MethodBase MethodBase
global::java.lang.Class Class
global::java.lang.invoke.LambdaForm.Name Name
IKVM.Runtime.RuntimeByteCodeJavaType DynamicOrAotTypeWrapper
static ParameterBuilder[] GetParameterBuilders(MethodBuilder mb, int parameterCount, string[] parameterNames)
static void GetParameterNamesFromSig(string sig, string[] parameterNames)
static void GetParameterNamesFromLVT(ClassFile.Method m, string[] parameterNames)
record struct MethodKey(string ClassName, string MethodName, string MethodSig)