Some compat fixes for .NET 5

This commit is contained in:
spaceflint 2021-02-13 23:16:20 +02:00
parent a6fa3eef08
commit 67ad9b0ccc
17 changed files with 235 additions and 39 deletions

View File

@ -57,6 +57,8 @@ System.IFormattable
System.IFormatProvider
System.InvalidCastException
System.IServiceProvider
System.IObservable`*
System.IObserver`*
System.Nullable`*
@ -188,6 +190,7 @@ System.Reflection.IReflect
System.Reflection.MemberInfo
System.Reflection.FieldInfo
System.Reflection.EventInfo
System.Reflection.ParameterAttributes
System.Reflection.ParameterInfo
System.Reflection.PropertyInfo
System.Reflection.MethodInfo

View File

@ -881,63 +881,56 @@ namespace system
{
ThrowIfNull(array);
if (index < 0 || length < 0)
throw new System.ArgumentOutOfRangeException();
if (array.len - index < length)
throw new System.ArgumentException();
throw new System.IndexOutOfRangeException();
var endIndex = index + length;
if (endIndex > array.len)
throw new System.IndexOutOfRangeException();
switch (array.arr)
{
case bool[] boolArray:
for (; length-- > 0; index++)
boolArray[index] = default(bool);
java.util.Arrays.fill(boolArray, index, endIndex, false);
break;
case sbyte[] byteArray:
for (; length-- > 0; index++)
byteArray[index] = default(sbyte);
java.util.Arrays.fill(byteArray, index, endIndex, (sbyte) 0);
break;
case char[] charArray:
for (; length-- > 0; index++)
charArray[index] = default(char);
java.util.Arrays.fill(charArray, index, endIndex, (char) 0);
break;
case short[] shortArray:
for (; length-- > 0; index++)
shortArray[index] = default(short);
java.util.Arrays.fill(shortArray, index, endIndex, (short) 0);
break;
case int[] intArray:
for (; length-- > 0; index++)
intArray[index] = default(int);
java.util.Arrays.fill(intArray, index, endIndex, (int) 0);
break;
case long[] longArray:
for (; length-- > 0; index++)
longArray[index] = default(long);
java.util.Arrays.fill(longArray, index, endIndex, (long) 0);
break;
case float[] floatArray:
for (; length-- > 0; index++)
floatArray[index] = default(float);
java.util.Arrays.fill(floatArray, index, endIndex, (float) 0);
break;
case double[] doubleArray:
for (; length-- > 0; index++)
doubleArray[index] = default(double);
java.util.Arrays.fill(doubleArray, index, endIndex, (double) 0);
break;
case object[] objectArray:
if (system.RuntimeType.IsValueClass(
((java.lang.Object) array.arr).getClass().getComponentType()))
((java.lang.Object) (object) objectArray)
.getClass().getComponentType()))
{
for (; length-- > 0; index++)
((ValueMethod) (ValueType) objectArray[index]).Clear();
}
else
{
for (; length-- > 0; index++)
objectArray[index] = null;
java.util.Arrays.fill(objectArray, index, endIndex, null);
}
break;
@ -946,6 +939,86 @@ namespace system
}
}
//
// Fill
//
public static void Fill<T>(T[] array, T value)
{
ThrowIfNull(array);
FillCommon(array, (object) value, 0, java.lang.reflect.Array.getLength(array));
}
public static void Fill<T>(T[] array, T value, int startIndex, int count)
{
ThrowIfNull(array);
if (startIndex < 0 || count < 0)
throw new System.IndexOutOfRangeException();
var endIndex = startIndex + count;
if (endIndex > java.lang.reflect.Array.getLength(array))
throw new System.IndexOutOfRangeException();
FillCommon(array, (object) value, startIndex, endIndex);
}
private static void FillCommon(object array, object value, int startIndex, int endIndex)
{
switch (array)
{
case bool[] boolArray:
java.util.Arrays.fill(boolArray, startIndex, endIndex, (bool) value);
break;
case sbyte[] byteArray:
java.util.Arrays.fill(byteArray, startIndex, endIndex, (sbyte) value);
break;
case char[] charArray:
java.util.Arrays.fill(charArray, startIndex, endIndex, (char) value);
break;
case short[] shortArray:
java.util.Arrays.fill(shortArray, startIndex, endIndex, (short) value);
break;
case int[] intArray:
java.util.Arrays.fill(intArray, startIndex, endIndex, (int) value);
break;
case long[] longArray:
java.util.Arrays.fill(longArray, startIndex, endIndex, (long) value);
break;
case float[] floatArray:
java.util.Arrays.fill(floatArray, startIndex, endIndex, (float) value);
break;
case double[] doubleArray:
java.util.Arrays.fill(doubleArray, startIndex, endIndex, (double) value);
break;
case object[] objectArray:
if (system.RuntimeType.IsValueClass(
((java.lang.Object) array).getClass().getComponentType()))
{
ValueType v = (ValueType) value;
for (; startIndex < endIndex; startIndex++)
((ValueMethod) v).CopyTo((ValueType) objectArray[startIndex]);
}
else
{
java.util.Arrays.fill(objectArray, startIndex, endIndex, value);
}
break;
default:
throw new System.InvalidOperationException();
}
}
//
// Initialize
//
public void Initialize()
{
var type = ((java.lang.Object) arr).getClass().getComponentType();

View File

@ -25,6 +25,8 @@ namespace system
// number of days between 1/1/0001 and 1/1/10000 is 3,652,059
const long MaxTicks = 3652059 * TicksPerDay - 1;
public static readonly DateTime MaxValue = new DateTime(MaxTicks, DateTimeKind.Unspecified);
//
// Constructors (Now)
//

View File

@ -33,7 +33,6 @@ namespace system
{
DelegateUtil.CopyBoxed(fromObj, toObj);
}
}
@ -161,8 +160,22 @@ namespace system
proxy = genericObject.TryCast(castToType);
else
proxy = Array.GetProxy(obj, castToType, true);
if (proxy == null)
{
if ( (obj != null) && (! castToType.IsGenericType)
&& castToType is RuntimeType castToRuntimeType
&& castToRuntimeType.JavaClassForArray()
.isAssignableFrom(((java.lang.Object) obj).getClass()))
{
// target type is not generic, but the object can be cast to
// it. this happens when both object and target type are one
// of the non-generic interfaces implemented by Array.
// see also IsArray() in GenericUtil::ShouldCallGenericCast.
return obj;
}
ThrowInvalidCastException(obj, castToType);
}
return proxy;
}

View File

@ -141,14 +141,17 @@ namespace system
try
{
// TODO: check if begins with NumberFormatInfo.Positive/NegativeSign
result = java.lang.Integer.parseInt(s.Trim());
return true;
if (s != null)
{
result = java.lang.Integer.parseInt(s.Trim());
return true;
}
}
catch (java.lang.NumberFormatException)
{
result = 0;
return false;
}
result = 0;
return false;
}

View File

@ -35,6 +35,7 @@ namespace system
int len = format.length();
bool explicit_width = false;
int width = -1;
if (len == 1)
width = 0;
@ -72,18 +73,22 @@ namespace system
case 'D':
c = isInt ? 'd' : (char) 0;
pfx = '0';
break;
case 'N':
if (isInt)
{
c = 'd';
pfx = ',';
sfx = "." + new string('0', width);
width = 0;
}
else
{
c = 'f';
explicit_width = true; // set width even if zero
}
pfx = ',';
break;
case 'P':
@ -116,7 +121,7 @@ namespace system
var format1 = "%";
if (pfx != 0)
format1 += pfx;
if (width != 0)
if (explicit_width || width != 0)
{
if (! isInt)
format1 += ".";

View File

@ -5,6 +5,10 @@ namespace system.runtime.interopservices
public static class Marshal
{
[java.attr.RetainType] private static java.util.concurrent.ConcurrentHashMap MarshalTypes =
new java.util.concurrent.ConcurrentHashMap();
public static int SizeOf(System.Type t)
{
var j = ((system.RuntimeType) t).JavaClassForArray();
@ -12,9 +16,26 @@ namespace system.runtime.interopservices
: (j == java.lang.Character.TYPE || j == java.lang.Short.TYPE) ? 2
: (j == java.lang.Integer.TYPE || j == java.lang.Float.TYPE) ? 4
: (j == java.lang.Long.TYPE || j == java.lang.Double.TYPE) ? 8
: MarshalTypes.get(t) is int sz ? sz
: throw new System.PlatformNotSupportedException();
}
public static bool SetComObjectData(object obj, object key, object data)
{
// this method is used to record extra types that Marshal.SizeOf
// should recognize, and the size returned for each such type
#pragma warning disable 0252
if (obj == typeof(Marshal) && key is System.Type && data is int)
{
MarshalTypes.put(key, data);
return true;
}
throw new System.PlatformNotSupportedException();
//return false;
}
}
}

View File

@ -145,7 +145,15 @@ namespace system
[java.attr.RetainName]
public static System.ValueType Assign(ValueType source)
=> new Span<T>((T[]) (object) (new ValueType[1] { source }));
{
return new Span<T>()
{
array = Reference.Box(new ValueType[1] { source }),
count = 1,
shift = Shiftof() + 1
};
// => new Span<T>((T[]) (object) (new ValueType[1] { source }));
}
[java.attr.RetainName]
public static Span<object> Assign(long zero)

View File

@ -186,6 +186,7 @@ namespace SpaceFlint.CilToJava
.Replace(']', '\uFF3D') // U+FF3D Fullwidth Right Square Bracket
.Replace('`', '\uFF40') // U+FF40 Fullwidth Grave Accent
.Replace('~', '\uFF5E') // U+FF40 Fullwidth Tilde
.Replace(' ', '\uFFE2') // U+FFE2 Fullwidth Not Sign
;
}

View File

@ -811,7 +811,7 @@ namespace SpaceFlint.CilToJava
var thisRef = stackMap.PopStack(CilMain.Where);
if (updateThis && thisRef.Equals(JavaStackMap.UninitializedThis))
{
// an 'uninitializedthis' first argument is updated in
// an 'uninitializedThis' first argument is updated in
// the stack frame after calling the super constructor
locals.UpdateThis(method.DeclType);
}

View File

@ -592,13 +592,15 @@ namespace SpaceFlint.CilToJava
var castType = (CilType) CilType.From(cilType);
JavaType castClass = CilType.From(cilType).AsWritableClass;
if (GenericUtil.ShouldCallGenericCast(stackTop, castType))
if ( GenericUtil.ShouldCallGenericCast(stackTop, castType)
|| castType.IsGenericParameter)
{
code.StackMap.PushStack(stackTop);
// casting to a generic type is done via GenericType.TestCast
GenericUtil.CastToGenericType(cilType, 0, code);
code.StackMap.PopStack(CilMain.Where); // stackTop
code.NewInstruction(0xC0 /* checkcast */, castClass, null);
if (! castType.IsGenericParameter)
code.NewInstruction(0xC0 /* checkcast */, castClass, null);
code.StackMap.PushStack(castClass);
}

View File

@ -403,7 +403,31 @@ namespace SpaceFlint.CilToJava
// is a value class that is assigned before the call to the
// base constructor.
if (fldType.IsValueClass)
if (fldType.IsGenericParameter)
{
// if the field has a generic type, we first need to allocate
// it (as would be done by ValueUtil.ConstructValue) and then
// copy the value on the stack into it
GenericUtil.LoadMaybeGeneric(fldType, code);
code.NewInstruction(0xB8 /* invokestatic */, GenericUtil.SystemGenericType,
new JavaMethodRef("New", CilType.SystemValueType, CilType.SystemTypeType));
// use dup_x1 to arrange the stack as (newObj, sourceObj, newObj)
code.NewInstruction(0x5A /* dup_x1 */, null, null);
stackMap.PushStack(fldType);
stackMap.PushStack(fldType);
// call GenericType.Copy(fromObj, toObj) in baselib
code.NewInstruction(0xB8 /* invokestatic */, GenericUtil.SystemGenericType,
new JavaMethod("Copy", JavaType.VoidType,
JavaType.ObjectType, JavaType.ObjectType));
stackMap.PopStack(CilMain.Where);
stackMap.PopStack(CilMain.Where);
}
else if (fldType.IsValueClass)
{
CilMethod.ValueMethod(CilMethod.ValueClone, code);
code.NewInstruction(0xC0 /* checkcast */, fldType.AsWritableClass, null);

View File

@ -136,6 +136,11 @@ namespace SpaceFlint.CilToJava
if (code.MaxStack < 1)
code.MaxStack = 1;
// we are injecting a call to super constructor at the very top,
// so local 0 should have the proper type, not uninitializedThis
code.StackMap.SetLocalInAllFrames(
0, CilType.From(new JavaType(0, 0, dataClass.Name)), null);
insertReturn = false;
}

View File

@ -600,9 +600,22 @@ namespace SpaceFlint.CilToJava
}
if (sameParameters)
{
//Console.WriteLine($"proxying {targetMethod} in class {targetMethod.DeclType}");
BuildGenericProxy2(baseMethod, targetMethod,
false, targetMethod.DeclType, intoClass);
if (baseMethod.Method.WithGenericParameters.ToString()
!= targetMethod.WithGenericParameters.ToString())
{
// the proxy method may have the same signature as the
// target method. for example in a generic class that
// inherits from a generic class:
// class A<T> { virtual T Method(T arg); }
// and class B<T> : A<T> { override T Method(T arg); }
// in such a case, we should not generate a specialized
// proxy for the generic method in class B.
//
//Console.WriteLine($"proxying {targetMethod} in class {targetMethod.DeclType}");
BuildGenericProxy2(baseMethod, targetMethod,
false, targetMethod.DeclType, intoClass);
}
return;
}
}

View File

@ -358,7 +358,7 @@ namespace SpaceFlint.JavaBinary
{
if (! frm.locals[index].Equals(type))
{
if (frm.locals[index] != Top)
if (Where != null && frm.locals[index] != Top)
throw Where.Exception($"local already assigned in stack frame");
frm.locals[index] = type;
}

View File

@ -23,8 +23,8 @@ namespace Tests
//TestDictionary();
TestSet();
TestStack();
TestHash();
}
@ -127,5 +127,18 @@ namespace Tests
}
}
public void TestHash()
{
var dict = new System.Collections.Hashtable();
dict["int1"] = (int) 10;
dict["int2"] = (int) 20;
int sum = 0;
foreach (var key in dict.Keys)
sum += (int) dict[key];
Console.WriteLine(sum);
}
}
}

View File

@ -16,6 +16,7 @@ namespace Tests
TestCompare();
TestCast("Test");
TestEncoding();
TestNumber();
}
@ -244,5 +245,14 @@ namespace Tests
Console.WriteLine(string.CompareOrdinal(aString, bString));
}
void TestNumber()
{
int x = 1;
var y = 33333.030303;
Console.WriteLine($"[{x:D3}] [{y:N0}]");
}
}
}