summaryrefslogtreecommitdiff
path: root/external/ikvm/runtime/ClassFile.cs
diff options
context:
space:
mode:
Diffstat (limited to 'external/ikvm/runtime/ClassFile.cs')
-rw-r--r--external/ikvm/runtime/ClassFile.cs107
1 files changed, 75 insertions, 32 deletions
diff --git a/external/ikvm/runtime/ClassFile.cs b/external/ikvm/runtime/ClassFile.cs
index c3cf3e8d5c..db684117b3 100644
--- a/external/ikvm/runtime/ClassFile.cs
+++ b/external/ikvm/runtime/ClassFile.cs
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2002-2012 Jeroen Frijters
+ Copyright (C) 2002-2013 Jeroen Frijters
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@@ -65,8 +65,7 @@ namespace IKVM.Internal
private const ushort FLAG_MASK_MAJORVERSION = 0xFF;
private const ushort FLAG_MASK_DEPRECATED = 0x100;
private const ushort FLAG_MASK_INTERNAL = 0x200;
- private const ushort FLAG_MASK_EFFECTIVELY_FINAL = 0x400;
- private const ushort FLAG_HAS_CALLERID = 0x800;
+ private const ushort FLAG_CALLERSENSITIVE = 0x400;
private ConstantPoolItemClass[] interfaces;
private Field[] fields;
private Method[] methods;
@@ -84,7 +83,7 @@ namespace IKVM.Internal
private static class SupportedVersions
{
internal static readonly int Minimum = 45;
- internal static readonly int Maximum = JVM.SafeGetEnvironmentVariable("IKVM_EXPERIMENTAL_JDK_8") != null ? 52 : 51;
+ internal static readonly int Maximum = Experimental.JDK_8 ? 52 : 51;
}
#if STATIC_COMPILER
@@ -424,8 +423,9 @@ namespace IKVM.Internal
}
else
{
- int class_index = br.ReadUInt16();
- int method_index = br.ReadUInt16();
+ ushort class_index = br.ReadUInt16();
+ ushort method_index = br.ReadUInt16();
+ ValidateConstantPoolItemClass(inputClassName, class_index);
if(method_index == 0)
{
enclosingMethod = new string[] {
@@ -436,7 +436,11 @@ namespace IKVM.Internal
}
else
{
- ConstantPoolItemNameAndType m = (ConstantPoolItemNameAndType)GetConstantPoolItem(method_index);
+ ConstantPoolItemNameAndType m = GetConstantPoolItem(method_index) as ConstantPoolItemNameAndType;
+ if(m == null)
+ {
+ throw new ClassFormatError("{0} (Bad constant pool index #{1})", inputClassName, method_index);
+ }
enclosingMethod = new string[] {
GetConstantPoolClass(class_index),
GetConstantPoolUtf8String(utf8_cp, m.name_index),
@@ -1211,19 +1215,6 @@ namespace IKVM.Internal
flags |= FLAG_MASK_INTERNAL;
}
- internal void SetEffectivelyFinal()
- {
- flags |= FLAG_MASK_EFFECTIVELY_FINAL;
- }
-
- internal bool IsEffectivelyFinal
- {
- get
- {
- return (flags & FLAG_MASK_EFFECTIVELY_FINAL) != 0;
- }
- }
-
internal bool HasInitializedFields
{
get
@@ -1429,7 +1420,7 @@ namespace IKVM.Internal
{
if(typeWrapper == VerifierTypeWrapper.Null)
{
- TypeWrapper tw = ClassLoaderWrapper.LoadClassNoThrow(thisType.GetClassLoader(), name);
+ TypeWrapper tw = ClassLoaderWrapper.LoadClassNoThrow(thisType.GetClassLoader(), name, true);
#if !STATIC_COMPILER && !FIRST_PASS
if(!tw.IsUnloadable)
{
@@ -1765,6 +1756,10 @@ namespace IKVM.Internal
private static MethodWrapper GetInterfaceMethod(TypeWrapper wrapper, string name, string sig)
{
+ if(wrapper.IsUnloadable)
+ {
+ return null;
+ }
MethodWrapper method = wrapper.GetMethodWrapper(name, sig, false);
if(method != null)
{
@@ -1786,7 +1781,7 @@ namespace IKVM.Internal
{
base.Link(thisType);
TypeWrapper wrapper = GetClassType();
- if(wrapper != null && !wrapper.IsUnloadable)
+ if(wrapper != null)
{
method = GetInterfaceMethod(wrapper, Name, Signature);
if(method == null)
@@ -1919,6 +1914,8 @@ namespace IKVM.Internal
case RefKind.invokeStatic:
case RefKind.newInvokeSpecial:
cpi = classFile.GetConstantPoolItem(method_index) as ConstantPoolItemMethodref;
+ if (cpi == null && classFile.MajorVersion >= 52 && (RefKind)ref_kind == RefKind.invokeStatic)
+ goto case RefKind.invokeInterface;
break;
case RefKind.invokeInterface:
cpi = classFile.GetConstantPoolItem(method_index) as ConstantPoolItemInterfaceMethodref;
@@ -2562,6 +2559,7 @@ namespace IKVM.Internal
private Code code;
private string[] exceptions;
private LowFreqData low;
+ private MethodParametersEntry[] parameters;
sealed class LowFreqData
{
@@ -2589,9 +2587,10 @@ namespace IKVM.Internal
if((ReferenceEquals(Name, StringConstants.INIT) && (IsStatic || IsSynchronized || IsFinal || IsAbstract || IsNative))
|| (IsPrivate && IsPublic) || (IsPrivate && IsProtected) || (IsPublic && IsProtected)
|| (IsAbstract && (IsFinal || IsNative || IsPrivate || IsStatic || IsSynchronized))
- || (classFile.IsInterface && (!IsPublic || !IsAbstract)))
+ || (classFile.IsInterface && classFile.MajorVersion <= 51 && (!IsPublic || IsFinal || IsNative || IsSynchronized || !IsAbstract))
+ || (classFile.IsInterface && classFile.MajorVersion >= 52 && (!(IsPublic || IsPrivate) || IsFinal || IsNative || IsSynchronized)))
{
- throw new ClassFormatError("{0} (Illegal method modifiers: 0x{1:X})", classFile.Name, access_flags);
+ throw new ClassFormatError("Method {0} in class {1} has illegal modifiers: 0x{2:X}", Name, classFile.Name, (int)access_flags);
}
}
int attributes_count = br.ReadUInt16();
@@ -2656,6 +2655,15 @@ namespace IKVM.Internal
goto default;
}
annotations = ReadAnnotations(br, classFile, utf8_cp);
+#if STATIC_COMPILER
+ foreach(object[] annot in annotations)
+ {
+ if(annot[1].Equals("Lsun/reflect/CallerSensitive;"))
+ {
+ flags |= FLAG_CALLERSENSITIVE;
+ }
+ }
+#endif
break;
case "RuntimeVisibleParameterAnnotations":
{
@@ -2723,10 +2731,6 @@ namespace IKVM.Internal
flags |= FLAG_MASK_INTERNAL;
}
}
- if(annot[1].Equals("Likvm/internal/HasCallerID;"))
- {
- flags |= FLAG_HAS_CALLERID;
- }
if(annot[1].Equals("Likvm/lang/DllExport;"))
{
string name = null;
@@ -2762,6 +2766,30 @@ namespace IKVM.Internal
}
break;
#endif
+ case "MethodParameters":
+ {
+ if(classFile.MajorVersion < 52)
+ {
+ goto default;
+ }
+ if(parameters != null)
+ {
+ throw new ClassFormatError("{0} (Duplicate MethodParameters attribute)", classFile.Name);
+ }
+ BigEndianBinaryReader rdr = br.Section(br.ReadUInt32());
+ byte parameters_count = rdr.ReadByte();
+ parameters = new MethodParametersEntry[parameters_count];
+ for(int j = 0; j < parameters_count; j++)
+ {
+ parameters[j].name = classFile.GetConstantPoolUtf8String(utf8_cp, rdr.ReadUInt16());
+ parameters[j].flags = rdr.ReadUInt16();
+ }
+ if(!rdr.IsAtEnd)
+ {
+ throw new ClassFormatError("{0} (MethodParameters attribute has wrong length)", classFile.Name);
+ }
+ break;
+ }
default:
br.Skip(br.ReadUInt32());
break;
@@ -2783,7 +2811,7 @@ namespace IKVM.Internal
code.verifyError = string.Format("Class {0}, method {1} signature {2}: No Code attribute", classFile.Name, this.Name, this.Signature);
return;
}
- throw new ClassFormatError("Method has no Code attribute");
+ throw new ClassFormatError("Absent Code attribute in method that is not native or abstract in class file " + classFile.Name);
}
}
}
@@ -2821,14 +2849,15 @@ namespace IKVM.Internal
}
}
- // for use by ikvmc only
- internal bool HasCallerIDAnnotation
+#if STATIC_COMPILER
+ internal bool IsCallerSensitive
{
get
{
- return (flags & FLAG_HAS_CALLERID) != 0;
+ return (flags & FLAG_CALLERSENSITIVE) != 0;
}
}
+#endif
internal string[] ExceptionsAttribute
{
@@ -2945,6 +2974,14 @@ namespace IKVM.Internal
}
}
+ internal MethodParametersEntry[] MethodParameters
+ {
+ get
+ {
+ return parameters;
+ }
+ }
+
internal bool HasJsr
{
get
@@ -3526,6 +3563,12 @@ namespace IKVM.Internal
internal string descriptor;
internal ushort index;
}
+
+ internal struct MethodParametersEntry
+ {
+ internal string name;
+ internal ushort flags;
+ }
}
internal Field GetField(string name, string sig)