2002-12-18 19:00:25 +03:00
/ *
2006-01-23 13:18:44 +03:00
Copyright ( C ) 2002 , 2003 , 2004 , 2005 , 2006 Jeroen Frijters
2002-12-18 19:00:25 +03:00
This software is provided ' as - is ' , without any express or implied
warranty . In no event will the authors be held liable for any damages
arising from the use of this software .
Permission is granted to anyone to use this software for any purpose ,
including commercial applications , and to alter it and redistribute it
freely , subject to the following restrictions :
1. The origin of this software must not be misrepresented ; you must not
claim that you wrote the original software . If you use this software
in a product , an acknowledgment in the product documentation would be
appreciated but is not required .
2. Altered source versions must be plainly marked as such , and must not be
misrepresented as being the original software .
3. This notice may not be removed or altered from any source distribution .
Jeroen Frijters
jeroen @frijters . net
* /
using System ;
using System.Collections ;
2005-12-07 12:06:32 +03:00
#if WHIDBEY
using System.Collections.Generic ;
#endif
2002-12-18 19:00:25 +03:00
using System.Reflection ;
2005-12-07 12:06:32 +03:00
#if ! COMPACT_FRAMEWORK
2002-12-18 19:00:25 +03:00
using System.Reflection.Emit ;
2005-12-07 12:06:32 +03:00
using ILGenerator = IKVM . Internal . CountingILGenerator ;
2005-12-29 18:48:32 +03:00
using Label = IKVM . Internal . CountingLabel ;
2005-12-07 12:06:32 +03:00
#endif
2002-12-18 19:00:25 +03:00
using System.Diagnostics ;
2005-05-23 12:24:07 +04:00
using System.Security ;
using System.Security.Permissions ;
2004-09-09 15:17:55 +04:00
using IKVM.Runtime ;
using IKVM.Attributes ;
2002-12-18 19:00:25 +03:00
2004-10-19 17:43:55 +04:00
2005-06-01 13:49:30 +04:00
namespace IKVM.Internal
2003-05-13 00:00:15 +04:00
{
2006-04-05 12:18:58 +04:00
struct ExModifiers
{
internal readonly Modifiers Modifiers ;
internal readonly bool IsInternal ;
internal ExModifiers ( Modifiers modifiers , bool isInternal )
{
this . Modifiers = modifiers ;
this . IsInternal = isInternal ;
}
}
2005-12-07 12:06:32 +03:00
#if ! COMPACT_FRAMEWORK
2005-06-01 13:49:30 +04:00
class EmitHelper
2004-03-08 18:18:47 +03:00
{
2005-06-01 13:49:30 +04:00
private static MethodInfo objectToString = typeof ( object ) . GetMethod ( "ToString" , BindingFlags . Public | BindingFlags . Instance , null , Type . EmptyTypes , null ) ;
2006-04-11 16:05:24 +04:00
private static MethodInfo verboseCastFailure = JVM . SafeGetEnvironmentVariable ( "IKVM_VERBOSE_CAST" ) = = null ? null : ByteCodeHelperMethods . VerboseCastFailure ;
2005-12-07 12:06:32 +03:00
static EmitHelper ( ) { }
2004-03-08 18:18:47 +03:00
2005-06-01 13:49:30 +04:00
internal static void Throw ( ILGenerator ilgen , string dottedClassName )
{
TypeWrapper exception = ClassLoaderWrapper . GetBootstrapClassLoader ( ) . LoadClassByDottedName ( dottedClassName ) ;
MethodWrapper mw = exception . GetMethodWrapper ( "<init>" , "()V" , false ) ;
mw . Link ( ) ;
mw . EmitNewobj ( ilgen ) ;
ilgen . Emit ( OpCodes . Throw ) ;
}
2003-05-30 16:08:59 +04:00
2005-06-01 13:49:30 +04:00
internal static void Throw ( ILGenerator ilgen , string dottedClassName , string message )
{
TypeWrapper exception = ClassLoaderWrapper . GetBootstrapClassLoader ( ) . LoadClassByDottedName ( dottedClassName ) ;
ilgen . Emit ( OpCodes . Ldstr , message ) ;
MethodWrapper mw = exception . GetMethodWrapper ( "<init>" , "(Ljava.lang.String;)V" , false ) ;
mw . Link ( ) ;
mw . EmitNewobj ( ilgen ) ;
ilgen . Emit ( OpCodes . Throw ) ;
}
internal static void NullCheck ( ILGenerator ilgen )
{
// I think this is the most efficient way to generate a NullReferenceException if the
// reference is null
ilgen . Emit ( OpCodes . Ldvirtftn , objectToString ) ;
2003-11-17 15:01:50 +03:00
ilgen . Emit ( OpCodes . Pop ) ;
}
2004-03-08 18:18:47 +03:00
2005-06-01 13:49:30 +04:00
internal static void Castclass ( ILGenerator ilgen , Type type )
{
if ( verboseCastFailure ! = null )
{
LocalBuilder lb = ilgen . DeclareLocal ( typeof ( object ) ) ;
ilgen . Emit ( OpCodes . Stloc , lb ) ;
ilgen . Emit ( OpCodes . Ldloc , lb ) ;
ilgen . Emit ( OpCodes . Isinst , type ) ;
ilgen . Emit ( OpCodes . Dup ) ;
Label ok = ilgen . DefineLabel ( ) ;
ilgen . Emit ( OpCodes . Brtrue_S , ok ) ;
ilgen . Emit ( OpCodes . Ldloc , lb ) ;
ilgen . Emit ( OpCodes . Brfalse_S , ok ) ; // handle null
ilgen . Emit ( OpCodes . Ldtoken , type ) ;
ilgen . Emit ( OpCodes . Ldloc , lb ) ;
ilgen . Emit ( OpCodes . Call , verboseCastFailure ) ;
ilgen . MarkLabel ( ok ) ;
}
else
{
ilgen . Emit ( OpCodes . Castclass , type ) ;
}
}
2005-02-11 17:46:58 +03:00
2005-06-01 13:49:30 +04:00
// This is basically the same as Castclass, except that it
// throws an IncompatibleClassChangeError on failure.
internal static void EmitAssertType ( ILGenerator ilgen , Type type )
2005-02-11 17:46:58 +03:00
{
LocalBuilder lb = ilgen . DeclareLocal ( typeof ( object ) ) ;
ilgen . Emit ( OpCodes . Stloc , lb ) ;
ilgen . Emit ( OpCodes . Ldloc , lb ) ;
ilgen . Emit ( OpCodes . Isinst , type ) ;
ilgen . Emit ( OpCodes . Dup ) ;
Label ok = ilgen . DefineLabel ( ) ;
2005-02-16 14:20:43 +03:00
ilgen . Emit ( OpCodes . Brtrue_S , ok ) ;
2005-02-11 17:46:58 +03:00
ilgen . Emit ( OpCodes . Ldloc , lb ) ;
2005-02-16 14:20:43 +03:00
ilgen . Emit ( OpCodes . Brfalse_S , ok ) ; // handle null
2005-06-01 13:49:30 +04:00
EmitHelper . Throw ( ilgen , "java.lang.IncompatibleClassChangeError" ) ;
2005-02-11 17:46:58 +03:00
ilgen . MarkLabel ( ok ) ;
}
}
2005-12-07 12:06:32 +03:00
#endif
2005-06-01 13:49:30 +04:00
class AttributeHelper
2005-02-16 14:20:43 +03:00
{
2005-12-07 12:06:32 +03:00
#if ! COMPACT_FRAMEWORK
2005-06-01 13:49:30 +04:00
private static CustomAttributeBuilder ghostInterfaceAttribute ;
private static CustomAttributeBuilder hideFromJavaAttribute ;
private static CustomAttributeBuilder deprecatedAttribute ;
2006-04-11 18:59:43 +04:00
#if STATIC_COMPILER
2005-06-01 13:49:30 +04:00
private static CustomAttributeBuilder editorBrowsableNever ;
2006-04-11 18:59:43 +04:00
#endif
2005-06-01 13:49:30 +04:00
private static ConstructorInfo implementsAttribute ;
private static ConstructorInfo throwsAttribute ;
private static ConstructorInfo sourceFileAttribute ;
2005-08-22 16:42:02 +04:00
private static ConstructorInfo lineNumberTableAttribute1 ;
private static ConstructorInfo lineNumberTableAttribute2 ;
2005-10-01 15:16:11 +04:00
private static ConstructorInfo enclosingMethodAttribute ;
private static ConstructorInfo signatureAttribute ;
private static CustomAttributeBuilder paramArrayAttribute ;
2005-12-07 12:06:32 +03:00
#endif
private static Type typeofRemappedClassAttribute = JVM . LoadType ( typeof ( RemappedClassAttribute ) ) ;
private static Type typeofRemappedTypeAttribute = JVM . LoadType ( typeof ( RemappedTypeAttribute ) ) ;
private static Type typeofModifiersAttribute = JVM . LoadType ( typeof ( ModifiersAttribute ) ) ;
private static Type typeofModifiers = JVM . LoadType ( typeof ( Modifiers ) ) ;
private static Type typeofRemappedInterfaceMethodAttribute = JVM . LoadType ( typeof ( RemappedInterfaceMethodAttribute ) ) ;
private static Type typeofNameSigAttribute = JVM . LoadType ( typeof ( NameSigAttribute ) ) ;
private static Type typeofJavaModuleAttribute = JVM . LoadType ( typeof ( JavaModuleAttribute ) ) ;
private static Type typeofSourceFileAttribute = JVM . LoadType ( typeof ( SourceFileAttribute ) ) ;
private static Type typeofLineNumberTableAttribute = JVM . LoadType ( typeof ( LineNumberTableAttribute ) ) ;
private static Type typeofEnclosingMethodAttribute = JVM . LoadType ( typeof ( EnclosingMethodAttribute ) ) ;
private static Type typeofSignatureAttribute = JVM . LoadType ( typeof ( SignatureAttribute ) ) ;
private static Type typeofInnerClassAttribute = JVM . LoadType ( typeof ( InnerClassAttribute ) ) ;
private static Type typeofImplementsAttribute = JVM . LoadType ( typeof ( ImplementsAttribute ) ) ;
private static Type typeofGhostInterfaceAttribute = JVM . LoadType ( typeof ( GhostInterfaceAttribute ) ) ;
private static Type typeofExceptionIsUnsafeForMappingAttribute = JVM . LoadType ( typeof ( ExceptionIsUnsafeForMappingAttribute ) ) ;
private static Type typeofThrowsAttribute = JVM . LoadType ( typeof ( ThrowsAttribute ) ) ;
private static Type typeofHideFromReflectionAttribute = JVM . LoadType ( typeof ( HideFromReflectionAttribute ) ) ;
private static Type typeofHideFromJavaAttribute = JVM . LoadType ( typeof ( HideFromJavaAttribute ) ) ;
private static Type typeofNoPackagePrefixAttribute = JVM . LoadType ( typeof ( NoPackagePrefixAttribute ) ) ;
private static Type typeofConstantValueAttribute = JVM . LoadType ( typeof ( ConstantValueAttribute ) ) ;
// make sure we don't get the "beforefieldinit" flag as that could cause our cctor to run before
// JVM.IsStaticCompiler is set
static AttributeHelper ( ) { }
2003-05-30 16:08:59 +04:00
2005-06-01 13:49:30 +04:00
private static object ParseValue ( TypeWrapper tw , string val )
2005-04-27 10:10:01 +04:00
{
2005-06-01 13:49:30 +04:00
if ( tw = = CoreClasses . java . lang . String . Wrapper )
{
return val ;
}
else if ( tw . TypeAsTBD . IsEnum )
{
2005-12-07 12:06:32 +03:00
#if WHIDBEY
if ( tw . TypeAsTBD . Assembly . ReflectionOnly )
{
// TODO implement full parsing semantics
FieldInfo field = tw . TypeAsTBD . GetField ( val ) ;
if ( field = = null )
{
throw new NotImplementedException ( "Parsing enum value: " + val ) ;
}
return field . GetRawConstantValue ( ) ;
}
#endif
2005-06-01 13:49:30 +04:00
return Enum . Parse ( tw . TypeAsTBD , val ) ;
}
else if ( tw . TypeAsTBD = = typeof ( Type ) )
{
return Type . GetType ( val , true ) ;
}
else if ( tw = = PrimitiveTypeWrapper . BOOLEAN )
{
return bool . Parse ( val ) ;
}
else if ( tw = = PrimitiveTypeWrapper . BYTE )
{
return ( byte ) sbyte . Parse ( val ) ;
}
else if ( tw = = PrimitiveTypeWrapper . CHAR )
{
return char . Parse ( val ) ;
}
else if ( tw = = PrimitiveTypeWrapper . SHORT )
{
return short . Parse ( val ) ;
}
else if ( tw = = PrimitiveTypeWrapper . INT )
{
return int . Parse ( val ) ;
}
else if ( tw = = PrimitiveTypeWrapper . FLOAT )
{
return float . Parse ( val ) ;
}
else if ( tw = = PrimitiveTypeWrapper . LONG )
{
return long . Parse ( val ) ;
}
else if ( tw = = PrimitiveTypeWrapper . DOUBLE )
{
return double . Parse ( val ) ;
}
else
{
throw new NotImplementedException ( ) ;
}
2005-04-27 10:10:01 +04:00
}
2006-04-10 13:09:09 +04:00
#if STATIC_COMPILER & & ! COMPACT_FRAMEWORK
2005-06-01 13:49:30 +04:00
private static void SetPropertiesAndFields ( Attribute attrib , IKVM . Internal . MapXml . Attribute attr )
2005-04-27 10:10:01 +04:00
{
2005-06-01 13:49:30 +04:00
Type t = attrib . GetType ( ) ;
if ( attr . Properties ! = null )
{
foreach ( IKVM . Internal . MapXml . Param prop in attr . Properties )
{
PropertyInfo pi = t . GetProperty ( prop . Name ) ;
pi . SetValue ( attrib , ParseValue ( ClassFile . FieldTypeWrapperFromSig ( ClassLoaderWrapper . GetBootstrapClassLoader ( ) , new Hashtable ( ) , prop . Sig ) , prop . Value ) , null ) ;
}
}
if ( attr . Fields ! = null )
{
foreach ( IKVM . Internal . MapXml . Param field in attr . Fields )
{
FieldInfo fi = t . GetField ( field . Name ) ;
fi . SetValue ( attrib , ParseValue ( ClassFile . FieldTypeWrapperFromSig ( ClassLoaderWrapper . GetBootstrapClassLoader ( ) , new Hashtable ( ) , field . Sig ) , field . Value ) ) ;
}
}
2005-04-27 10:10:01 +04:00
}
2005-06-01 13:49:30 +04:00
internal static Attribute InstantiatePseudoCustomAttribute ( IKVM . Internal . MapXml . Attribute attr )
2005-04-27 10:10:01 +04:00
{
2005-12-07 12:06:32 +03:00
Type t = StaticCompiler . GetType ( attr . Type ) ;
2005-06-01 13:49:30 +04:00
Type [ ] argTypes ;
object [ ] args ;
GetAttributeArgsAndTypes ( attr , out argTypes , out args ) ;
ConstructorInfo ci = t . GetConstructor ( argTypes ) ;
Attribute attrib = ci . Invoke ( args ) as Attribute ;
SetPropertiesAndFields ( attrib , attr ) ;
return attrib ;
2005-04-27 10:10:01 +04:00
}
2005-06-01 13:49:30 +04:00
private static bool IsCodeAccessSecurityAttribute ( IKVM . Internal . MapXml . Attribute attr , out SecurityAction action , out PermissionSet pset )
2005-04-27 10:10:01 +04:00
{
2005-06-01 13:49:30 +04:00
action = SecurityAction . Deny ;
pset = null ;
if ( attr . Type ! = null )
{
2005-12-07 12:06:32 +03:00
Type t = StaticCompiler . GetType ( attr . Type ) ;
2005-06-01 13:49:30 +04:00
if ( typeof ( CodeAccessSecurityAttribute ) . IsAssignableFrom ( t ) )
{
Type [ ] argTypes ;
object [ ] args ;
GetAttributeArgsAndTypes ( attr , out argTypes , out args ) ;
ConstructorInfo ci = t . GetConstructor ( argTypes ) ;
CodeAccessSecurityAttribute attrib = ci . Invoke ( args ) as CodeAccessSecurityAttribute ;
SetPropertiesAndFields ( attrib , attr ) ;
action = attrib . Action ;
pset = new PermissionSet ( PermissionState . None ) ;
pset . AddPermission ( attrib . CreatePermission ( ) ) ;
return true ;
}
}
return false ;
2005-04-27 10:10:01 +04:00
}
2005-06-01 13:49:30 +04:00
internal static void SetCustomAttribute ( TypeBuilder tb , IKVM . Internal . MapXml . Attribute attr )
2005-04-27 10:10:01 +04:00
{
2005-06-01 13:49:30 +04:00
SecurityAction action ;
PermissionSet pset ;
if ( IsCodeAccessSecurityAttribute ( attr , out action , out pset ) )
{
tb . AddDeclarativeSecurity ( action , pset ) ;
}
else
{
tb . SetCustomAttribute ( CreateCustomAttribute ( attr ) ) ;
}
2005-04-27 10:10:01 +04:00
}
2005-06-01 13:49:30 +04:00
internal static void SetCustomAttribute ( FieldBuilder fb , IKVM . Internal . MapXml . Attribute attr )
2005-04-27 10:10:01 +04:00
{
2005-06-01 13:49:30 +04:00
fb . SetCustomAttribute ( CreateCustomAttribute ( attr ) ) ;
2005-04-27 10:10:01 +04:00
}
2005-06-01 13:49:30 +04:00
internal static void SetCustomAttribute ( ParameterBuilder pb , IKVM . Internal . MapXml . Attribute attr )
2005-04-27 10:10:01 +04:00
{
2005-06-01 13:49:30 +04:00
pb . SetCustomAttribute ( CreateCustomAttribute ( attr ) ) ;
2005-04-27 10:10:01 +04:00
}
2005-06-01 13:49:30 +04:00
internal static void SetCustomAttribute ( MethodBuilder mb , IKVM . Internal . MapXml . Attribute attr )
2005-05-27 16:44:06 +04:00
{
2005-06-01 13:49:30 +04:00
SecurityAction action ;
PermissionSet pset ;
if ( IsCodeAccessSecurityAttribute ( attr , out action , out pset ) )
2005-05-27 16:44:06 +04:00
{
2005-06-01 13:49:30 +04:00
mb . AddDeclarativeSecurity ( action , pset ) ;
2005-05-27 16:44:06 +04:00
}
2005-06-01 13:49:30 +04:00
else
2005-05-27 16:44:06 +04:00
{
2005-06-01 13:49:30 +04:00
mb . SetCustomAttribute ( CreateCustomAttribute ( attr ) ) ;
2005-05-27 16:44:06 +04:00
}
}
2005-06-01 13:49:30 +04:00
internal static void SetCustomAttribute ( ConstructorBuilder cb , IKVM . Internal . MapXml . Attribute attr )
2005-05-23 12:24:07 +04:00
{
2005-06-01 13:49:30 +04:00
SecurityAction action ;
PermissionSet pset ;
if ( IsCodeAccessSecurityAttribute ( attr , out action , out pset ) )
2005-05-23 12:24:07 +04:00
{
2005-06-01 13:49:30 +04:00
cb . AddDeclarativeSecurity ( action , pset ) ;
}
else
{
cb . SetCustomAttribute ( CreateCustomAttribute ( attr ) ) ;
2005-05-23 12:24:07 +04:00
}
}
2005-06-01 13:49:30 +04:00
internal static void SetCustomAttribute ( PropertyBuilder pb , IKVM . Internal . MapXml . Attribute attr )
2005-05-23 12:24:07 +04:00
{
2005-06-01 13:49:30 +04:00
pb . SetCustomAttribute ( CreateCustomAttribute ( attr ) ) ;
2005-05-23 12:24:07 +04:00
}
2005-06-01 13:49:30 +04:00
internal static void SetCustomAttribute ( AssemblyBuilder ab , IKVM . Internal . MapXml . Attribute attr )
2005-05-23 12:24:07 +04:00
{
2005-06-01 13:49:30 +04:00
ab . SetCustomAttribute ( CreateCustomAttribute ( attr ) ) ;
2005-05-23 12:24:07 +04:00
}
2005-06-01 13:49:30 +04:00
private static void GetAttributeArgsAndTypes ( IKVM . Internal . MapXml . Attribute attr , out Type [ ] argTypes , out object [ ] args )
2005-05-23 12:24:07 +04:00
{
2005-06-01 13:49:30 +04:00
// TODO add error handling
TypeWrapper [ ] twargs = ClassFile . ArgTypeWrapperListFromSig ( ClassLoaderWrapper . GetBootstrapClassLoader ( ) , new Hashtable ( ) , attr . Sig ) ;
argTypes = new Type [ twargs . Length ] ;
args = new object [ argTypes . Length ] ;
for ( int i = 0 ; i < twargs . Length ; i + + )
{
argTypes [ i ] = twargs [ i ] . TypeAsSignatureType ;
TypeWrapper tw = twargs [ i ] ;
if ( tw = = CoreClasses . java . lang . Object . Wrapper )
{
tw = ClassFile . FieldTypeWrapperFromSig ( ClassLoaderWrapper . GetBootstrapClassLoader ( ) , new Hashtable ( ) , attr . Params [ i ] . Sig ) ;
}
if ( tw . IsArray )
{
Array arr = Array . CreateInstance ( tw . ElementTypeWrapper . TypeAsArrayType , attr . Params [ i ] . Elements . Length ) ;
for ( int j = 0 ; j < arr . Length ; j + + )
{
arr . SetValue ( ParseValue ( tw . ElementTypeWrapper , attr . Params [ i ] . Elements [ j ] . Value ) , j ) ;
}
args [ i ] = arr ;
}
else
{
args [ i ] = ParseValue ( tw , attr . Params [ i ] . Value ) ;
}
}
2005-05-23 12:24:07 +04:00
}
2005-06-01 13:49:30 +04:00
private static CustomAttributeBuilder CreateCustomAttribute ( IKVM . Internal . MapXml . Attribute attr )
2005-04-27 10:10:01 +04:00
{
2005-06-01 13:49:30 +04:00
// TODO add error handling
Type [ ] argTypes ;
object [ ] args ;
GetAttributeArgsAndTypes ( attr , out argTypes , out args ) ;
if ( attr . Type ! = null )
2005-04-27 10:10:01 +04:00
{
2005-12-07 12:06:32 +03:00
Type t = StaticCompiler . GetType ( attr . Type ) ;
2005-06-01 13:49:30 +04:00
if ( typeof ( CodeAccessSecurityAttribute ) . IsAssignableFrom ( t ) )
{
throw new NotImplementedException ( "CodeAccessSecurityAttribute support not implemented" ) ;
}
ConstructorInfo ci = t . GetConstructor ( argTypes ) ;
2005-12-07 12:06:32 +03:00
if ( ci = = null )
{
throw new InvalidOperationException ( string . Format ( "Constructor missing: {0}::<init>{1}" , attr . Class , attr . Sig ) ) ;
}
2005-06-01 13:49:30 +04:00
PropertyInfo [ ] namedProperties ;
object [ ] propertyValues ;
if ( attr . Properties ! = null )
{
namedProperties = new PropertyInfo [ attr . Properties . Length ] ;
propertyValues = new object [ attr . Properties . Length ] ;
for ( int i = 0 ; i < namedProperties . Length ; i + + )
{
namedProperties [ i ] = t . GetProperty ( attr . Properties [ i ] . Name ) ;
propertyValues [ i ] = ParseValue ( ClassFile . FieldTypeWrapperFromSig ( ClassLoaderWrapper . GetBootstrapClassLoader ( ) , new Hashtable ( ) , attr . Properties [ i ] . Sig ) , attr . Properties [ i ] . Value ) ;
}
}
else
{
namedProperties = new PropertyInfo [ 0 ] ;
propertyValues = new object [ 0 ] ;
}
FieldInfo [ ] namedFields ;
object [ ] fieldValues ;
if ( attr . Fields ! = null )
{
namedFields = new FieldInfo [ attr . Fields . Length ] ;
fieldValues = new object [ attr . Fields . Length ] ;
for ( int i = 0 ; i < namedFields . Length ; i + + )
{
namedFields [ i ] = t . GetField ( attr . Fields [ i ] . Name ) ;
fieldValues [ i ] = ParseValue ( ClassFile . FieldTypeWrapperFromSig ( ClassLoaderWrapper . GetBootstrapClassLoader ( ) , new Hashtable ( ) , attr . Fields [ i ] . Sig ) , attr . Fields [ i ] . Value ) ;
}
}
else
{
namedFields = new FieldInfo [ 0 ] ;
fieldValues = new object [ 0 ] ;
}
return new CustomAttributeBuilder ( ci , args , namedProperties , propertyValues , namedFields , fieldValues ) ;
2005-04-27 10:10:01 +04:00
}
2005-06-01 13:49:30 +04:00
else
2005-04-27 10:10:01 +04:00
{
2005-06-01 13:49:30 +04:00
if ( attr . Properties ! = null )
{
throw new NotImplementedException ( "Setting property values on Java attributes is not implemented" ) ;
}
TypeWrapper t = ClassLoaderWrapper . LoadClassCritical ( attr . Class ) ;
MethodWrapper mw = t . GetMethodWrapper ( "<init>" , attr . Sig , false ) ;
mw . Link ( ) ;
ConstructorInfo ci = ( ConstructorInfo ) mw . GetMethod ( ) ;
2005-12-07 12:06:32 +03:00
if ( ci = = null )
{
throw new InvalidOperationException ( string . Format ( "Constructor missing: {0}::<init>{1}" , attr . Class , attr . Sig ) ) ;
}
2005-06-01 13:49:30 +04:00
FieldInfo [ ] namedFields ;
object [ ] fieldValues ;
if ( attr . Fields ! = null )
{
namedFields = new FieldInfo [ attr . Fields . Length ] ;
fieldValues = new object [ attr . Fields . Length ] ;
for ( int i = 0 ; i < namedFields . Length ; i + + )
{
FieldWrapper fw = t . GetFieldWrapper ( attr . Fields [ i ] . Name , attr . Fields [ i ] . Sig ) ;
fw . Link ( ) ;
namedFields [ i ] = fw . GetField ( ) ;
fieldValues [ i ] = ParseValue ( ClassFile . FieldTypeWrapperFromSig ( ClassLoaderWrapper . GetBootstrapClassLoader ( ) , new Hashtable ( ) , attr . Fields [ i ] . Sig ) , attr . Fields [ i ] . Value ) ;
}
}
else
2005-04-27 10:10:01 +04:00
{
2005-06-01 13:49:30 +04:00
namedFields = new FieldInfo [ 0 ] ;
fieldValues = new object [ 0 ] ;
2005-04-27 10:10:01 +04:00
}
2005-06-01 13:49:30 +04:00
return new CustomAttributeBuilder ( ci , args , namedFields , fieldValues ) ;
2005-04-27 10:10:01 +04:00
}
2005-06-01 13:49:30 +04:00
}
#endif
2005-12-07 12:06:32 +03:00
#if ! COMPACT_FRAMEWORK
2006-04-10 13:09:09 +04:00
#if STATIC_COMPILER
2005-06-01 13:49:30 +04:00
internal static void SetEditorBrowsableNever ( MethodBuilder mb )
{
if ( editorBrowsableNever = = null )
2005-04-27 10:10:01 +04:00
{
2006-04-10 13:09:09 +04:00
editorBrowsableNever = new CustomAttributeBuilder ( StaticCompiler . GetType ( "System.ComponentModel.EditorBrowsableAttribute" ) . GetConstructor ( new Type [ ] { StaticCompiler . GetType ( "System.ComponentModel.EditorBrowsableState" ) } ) , new object [ ] { ( int ) System . ComponentModel . EditorBrowsableState . Never } ) ;
2005-04-27 10:10:01 +04:00
}
2005-06-01 13:49:30 +04:00
mb . SetCustomAttribute ( editorBrowsableNever ) ;
2005-04-27 10:10:01 +04:00
}
2005-05-23 12:24:07 +04:00
2005-06-01 13:49:30 +04:00
internal static void SetEditorBrowsableNever ( PropertyBuilder pb )
2005-04-27 10:10:01 +04:00
{
2005-06-01 13:49:30 +04:00
if ( editorBrowsableNever = = null )
2005-05-23 12:24:07 +04:00
{
2006-04-10 13:09:09 +04:00
editorBrowsableNever = new CustomAttributeBuilder ( StaticCompiler . GetType ( "System.ComponentModel.EditorBrowsableAttribute" ) . GetConstructor ( new Type [ ] { StaticCompiler . GetType ( "System.ComponentModel.EditorBrowsableState" ) } ) , new object [ ] { ( int ) System . ComponentModel . EditorBrowsableState . Never } ) ;
2005-05-23 12:24:07 +04:00
}
2005-06-01 13:49:30 +04:00
pb . SetCustomAttribute ( editorBrowsableNever ) ;
}
2006-04-10 13:09:09 +04:00
#endif // STATIC_COMPILER
2005-06-01 13:49:30 +04:00
internal static void SetDeprecatedAttribute ( MethodBase mb )
{
if ( deprecatedAttribute = = null )
2005-04-27 10:10:01 +04:00
{
2005-06-01 13:49:30 +04:00
deprecatedAttribute = new CustomAttributeBuilder ( typeof ( ObsoleteAttribute ) . GetConstructor ( Type . EmptyTypes ) , new object [ 0 ] ) ;
2005-04-27 10:10:01 +04:00
}
2005-06-01 13:49:30 +04:00
MethodBuilder method = mb as MethodBuilder ;
if ( method ! = null )
2005-04-27 10:10:01 +04:00
{
2005-06-01 13:49:30 +04:00
method . SetCustomAttribute ( deprecatedAttribute ) ;
2005-04-27 10:10:01 +04:00
}
2005-06-01 13:49:30 +04:00
else
2005-04-27 10:10:01 +04:00
{
2005-06-01 13:49:30 +04:00
( ( ConstructorBuilder ) mb ) . SetCustomAttribute ( deprecatedAttribute ) ;
2005-04-27 10:10:01 +04:00
}
2005-06-01 13:49:30 +04:00
}
internal static void SetDeprecatedAttribute ( TypeBuilder tb )
{
if ( deprecatedAttribute = = null )
2005-04-27 10:10:01 +04:00
{
2005-06-01 13:49:30 +04:00
deprecatedAttribute = new CustomAttributeBuilder ( typeof ( ObsoleteAttribute ) . GetConstructor ( Type . EmptyTypes ) , new object [ 0 ] ) ;
2005-04-27 10:10:01 +04:00
}
2005-06-01 13:49:30 +04:00
tb . SetCustomAttribute ( deprecatedAttribute ) ;
2005-04-27 10:10:01 +04:00
}
2005-06-01 13:49:30 +04:00
internal static void SetDeprecatedAttribute ( FieldBuilder fb )
2005-04-27 10:10:01 +04:00
{
2005-06-01 13:49:30 +04:00
if ( deprecatedAttribute = = null )
2005-04-27 10:10:01 +04:00
{
2005-06-01 13:49:30 +04:00
deprecatedAttribute = new CustomAttributeBuilder ( typeof ( ObsoleteAttribute ) . GetConstructor ( Type . EmptyTypes ) , new object [ 0 ] ) ;
2005-04-27 10:10:01 +04:00
}
2005-06-01 13:49:30 +04:00
fb . SetCustomAttribute ( deprecatedAttribute ) ;
}
internal static void SetThrowsAttribute ( MethodBase mb , string [ ] exceptions )
{
if ( exceptions ! = null & & exceptions . Length ! = 0 )
2005-04-27 10:10:01 +04:00
{
2005-06-01 13:49:30 +04:00
if ( throwsAttribute = = null )
2005-04-27 10:10:01 +04:00
{
2005-12-07 12:06:32 +03:00
throwsAttribute = typeofThrowsAttribute . GetConstructor ( new Type [ ] { typeof ( string [ ] ) } ) ;
2005-06-01 13:49:30 +04:00
}
if ( mb is MethodBuilder )
{
MethodBuilder method = ( MethodBuilder ) mb ;
method . SetCustomAttribute ( new CustomAttributeBuilder ( throwsAttribute , new object [ ] { exceptions } ) ) ;
}
else
{
ConstructorBuilder constructor = ( ConstructorBuilder ) mb ;
constructor . SetCustomAttribute ( new CustomAttributeBuilder ( throwsAttribute , new object [ ] { exceptions } ) ) ;
2005-04-27 10:10:01 +04:00
}
}
2004-11-23 20:46:39 +03:00
}
2005-06-01 13:49:30 +04:00
internal static void SetGhostInterface ( TypeBuilder typeBuilder )
2004-11-23 20:46:39 +03:00
{
2005-06-01 13:49:30 +04:00
if ( ghostInterfaceAttribute = = null )
{
2005-12-07 12:06:32 +03:00
ghostInterfaceAttribute = new CustomAttributeBuilder ( typeofGhostInterfaceAttribute . GetConstructor ( Type . EmptyTypes ) , new object [ 0 ] ) ;
2005-06-01 13:49:30 +04:00
}
typeBuilder . SetCustomAttribute ( ghostInterfaceAttribute ) ;
2004-11-23 20:46:39 +03:00
}
2003-11-17 15:01:50 +03:00
2005-08-14 19:49:50 +04:00
internal static void HideFromReflection ( MethodBuilder mb )
2003-11-17 15:01:50 +03:00
{
2005-12-07 12:06:32 +03:00
CustomAttributeBuilder cab = new CustomAttributeBuilder ( typeofHideFromReflectionAttribute . GetConstructor ( Type . EmptyTypes ) , new object [ 0 ] ) ;
2005-06-01 13:49:30 +04:00
mb . SetCustomAttribute ( cab ) ;
2003-11-17 15:01:50 +03:00
}
2005-06-01 13:49:30 +04:00
2005-08-14 19:49:50 +04:00
internal static void HideFromReflection ( FieldBuilder fb )
2003-11-17 15:01:50 +03:00
{
2005-12-07 12:06:32 +03:00
CustomAttributeBuilder cab = new CustomAttributeBuilder ( typeofHideFromReflectionAttribute . GetConstructor ( Type . EmptyTypes ) , new object [ 0 ] ) ;
2005-08-14 19:49:50 +04:00
fb . SetCustomAttribute ( cab ) ;
}
internal static void HideFromReflection ( PropertyBuilder pb )
{
2005-12-07 12:06:32 +03:00
CustomAttributeBuilder cab = new CustomAttributeBuilder ( typeofHideFromReflectionAttribute . GetConstructor ( Type . EmptyTypes ) , new object [ 0 ] ) ;
2005-08-14 19:49:50 +04:00
pb . SetCustomAttribute ( cab ) ;
}
2006-04-10 13:09:09 +04:00
#endif // !COMPACT_FRAMEWORK
2005-08-14 19:49:50 +04:00
internal static bool IsHideFromReflection ( MethodInfo mi )
{
2005-12-07 12:06:32 +03:00
return IsDefined ( mi , typeofHideFromReflectionAttribute ) ;
2005-08-14 19:49:50 +04:00
}
internal static bool IsHideFromReflection ( FieldInfo fi )
{
2005-12-07 12:06:32 +03:00
return IsDefined ( fi , typeofHideFromReflectionAttribute ) ;
2005-08-14 19:49:50 +04:00
}
internal static bool IsHideFromReflection ( PropertyInfo pi )
{
2005-12-07 12:06:32 +03:00
return IsDefined ( pi , typeofHideFromReflectionAttribute ) ;
2003-11-17 15:01:50 +03:00
}
2005-06-01 13:49:30 +04:00
2005-12-07 12:06:32 +03:00
#if ! COMPACT_FRAMEWORK
2005-06-01 13:49:30 +04:00
internal static void HideFromJava ( TypeBuilder typeBuilder )
2003-11-17 15:01:50 +03:00
{
2005-06-01 13:49:30 +04:00
if ( hideFromJavaAttribute = = null )
{
2005-12-07 12:06:32 +03:00
hideFromJavaAttribute = new CustomAttributeBuilder ( typeofHideFromJavaAttribute . GetConstructor ( Type . EmptyTypes ) , new object [ 0 ] ) ;
2005-06-01 13:49:30 +04:00
}
typeBuilder . SetCustomAttribute ( hideFromJavaAttribute ) ;
2003-11-17 15:01:50 +03:00
}
2005-06-01 13:49:30 +04:00
internal static void HideFromJava ( ConstructorBuilder cb )
2003-11-17 15:01:50 +03:00
{
2005-06-01 13:49:30 +04:00
if ( hideFromJavaAttribute = = null )
{
2005-12-07 12:06:32 +03:00
hideFromJavaAttribute = new CustomAttributeBuilder ( typeofHideFromJavaAttribute . GetConstructor ( Type . EmptyTypes ) , new object [ 0 ] ) ;
2005-06-01 13:49:30 +04:00
}
cb . SetCustomAttribute ( hideFromJavaAttribute ) ;
2003-11-17 15:01:50 +03:00
}
2005-06-01 13:49:30 +04:00
internal static void HideFromJava ( MethodBuilder mb )
2003-11-17 15:01:50 +03:00
{
2005-06-01 13:49:30 +04:00
if ( hideFromJavaAttribute = = null )
{
2005-12-07 12:06:32 +03:00
hideFromJavaAttribute = new CustomAttributeBuilder ( typeofHideFromJavaAttribute . GetConstructor ( Type . EmptyTypes ) , new object [ 0 ] ) ;
2005-06-01 13:49:30 +04:00
}
mb . SetCustomAttribute ( hideFromJavaAttribute ) ;
2003-11-17 15:01:50 +03:00
}
2005-06-01 13:49:30 +04:00
internal static void HideFromJava ( FieldBuilder fb )
2003-11-17 15:01:50 +03:00
{
2005-06-01 13:49:30 +04:00
if ( hideFromJavaAttribute = = null )
2003-11-17 15:01:50 +03:00
{
2005-12-07 12:06:32 +03:00
hideFromJavaAttribute = new CustomAttributeBuilder ( typeofHideFromJavaAttribute . GetConstructor ( Type . EmptyTypes ) , new object [ 0 ] ) ;
2003-11-17 15:01:50 +03:00
}
2005-06-01 13:49:30 +04:00
fb . SetCustomAttribute ( hideFromJavaAttribute ) ;
}
2005-12-07 12:06:32 +03:00
#endif
internal static bool IsHideFromJava ( Type type )
{
return IsDefined ( type , typeofHideFromJavaAttribute ) ;
}
2005-06-01 13:49:30 +04:00
internal static bool IsHideFromJava ( MemberInfo mi )
{
// NOTE all privatescope fields and methods are "hideFromJava"
// because Java cannot deal with the potential name clashes
FieldInfo fi = mi as FieldInfo ;
if ( fi ! = null & & ( fi . Attributes & FieldAttributes . FieldAccessMask ) = = FieldAttributes . PrivateScope )
2003-11-17 15:01:50 +03:00
{
2005-06-01 13:49:30 +04:00
return true ;
2003-11-17 15:01:50 +03:00
}
2005-06-01 13:49:30 +04:00
MethodBase mb = mi as MethodBase ;
if ( mb ! = null & & ( mb . Attributes & MethodAttributes . MemberAccessMask ) = = MethodAttributes . PrivateScope )
2003-11-17 15:01:50 +03:00
{
2005-06-01 13:49:30 +04:00
return true ;
2003-11-17 15:01:50 +03:00
}
2005-12-07 12:06:32 +03:00
return IsDefined ( mi , typeofHideFromJavaAttribute ) ;
2003-11-17 15:01:50 +03:00
}
2003-10-17 12:08:31 +04:00
2005-12-07 12:06:32 +03:00
#if ! COMPACT_FRAMEWORK
2005-06-01 13:49:30 +04:00
internal static void SetImplementsAttribute ( TypeBuilder typeBuilder , TypeWrapper [ ] ifaceWrappers )
2003-10-17 12:08:31 +04:00
{
2005-06-01 13:49:30 +04:00
if ( ifaceWrappers ! = null & & ifaceWrappers . Length ! = 0 )
{
string [ ] interfaces = new string [ ifaceWrappers . Length ] ;
for ( int i = 0 ; i < interfaces . Length ; i + + )
{
interfaces [ i ] = ifaceWrappers [ i ] . Name ;
}
if ( implementsAttribute = = null )
{
2005-12-07 12:06:32 +03:00
implementsAttribute = typeofImplementsAttribute . GetConstructor ( new Type [ ] { typeof ( string [ ] ) } ) ;
2005-06-01 13:49:30 +04:00
}
typeBuilder . SetCustomAttribute ( new CustomAttributeBuilder ( implementsAttribute , new object [ ] { interfaces } ) ) ;
}
}
2005-12-07 12:06:32 +03:00
#endif
internal static bool IsGhostInterface ( Type type )
{
return IsDefined ( type , typeofGhostInterfaceAttribute ) ;
}
internal static bool IsRemappedType ( Type type )
{
return IsDefined ( type , typeofRemappedTypeAttribute ) ;
}
internal static bool IsExceptionIsUnsafeForMapping ( Type type )
{
return IsDefined ( type , typeofExceptionIsUnsafeForMappingAttribute ) ;
}
internal static ModifiersAttribute GetModifiersAttribute ( Type type )
{
#if WHIDBEY
2005-12-19 18:12:49 +03:00
if ( JVM . IsStaticCompiler | | JVM . IsIkvmStub )
2005-12-07 12:06:32 +03:00
{
foreach ( CustomAttributeData cad in CustomAttributeData . GetCustomAttributes ( type ) )
{
if ( cad . Constructor . DeclaringType = = typeofModifiersAttribute )
{
IList < CustomAttributeTypedArgument > args = cad . ConstructorArguments ;
2006-04-05 12:18:58 +04:00
if ( args . Count = = 2 )
{
return new ModifiersAttribute ( ( Modifiers ) args [ 0 ] . Value , ( bool ) args [ 1 ] . Value ) ;
}
2005-12-07 12:06:32 +03:00
return new ModifiersAttribute ( ( Modifiers ) args [ 0 ] . Value ) ;
}
}
return null ;
}
#endif
object [ ] attr = type . GetCustomAttributes ( typeof ( ModifiersAttribute ) , false ) ;
2006-04-05 12:18:58 +04:00
return attr . Length = = 1 ? ( ModifiersAttribute ) attr [ 0 ] : null ;
2005-12-07 12:06:32 +03:00
}
2004-08-17 13:05:21 +04:00
2006-04-05 12:18:58 +04:00
internal static ExModifiers GetModifiers ( MethodBase mb , bool assemblyIsPrivate )
2003-10-17 12:08:31 +04:00
{
2005-12-07 12:06:32 +03:00
#if WHIDBEY
2005-12-19 18:12:49 +03:00
if ( JVM . IsStaticCompiler | | JVM . IsIkvmStub )
2005-06-01 13:49:30 +04:00
{
2005-12-07 12:06:32 +03:00
foreach ( CustomAttributeData cad in CustomAttributeData . GetCustomAttributes ( mb ) )
{
if ( cad . Constructor . DeclaringType = = typeofModifiersAttribute )
{
IList < CustomAttributeTypedArgument > args = cad . ConstructorArguments ;
2006-04-05 12:18:58 +04:00
if ( args . Count = = 2 )
{
return new ExModifiers ( ( Modifiers ) args [ 0 ] . Value , ( bool ) args [ 1 ] . Value ) ;
}
return new ExModifiers ( ( Modifiers ) args [ 0 ] . Value , false ) ;
2005-12-07 12:06:32 +03:00
}
}
}
else
#endif
{
object [ ] customAttribute = mb . GetCustomAttributes ( typeof ( ModifiersAttribute ) , false ) ;
if ( customAttribute . Length = = 1 )
{
2006-04-05 12:18:58 +04:00
ModifiersAttribute mod = ( ModifiersAttribute ) customAttribute [ 0 ] ;
return new ExModifiers ( mod . Modifiers , mod . IsInternal ) ;
2005-12-07 12:06:32 +03:00
}
2005-06-01 13:49:30 +04:00
}
Modifiers modifiers = 0 ;
if ( mb . IsPublic )
{
modifiers | = Modifiers . Public ;
}
else if ( mb . IsPrivate )
{
modifiers | = Modifiers . Private ;
}
else if ( mb . IsFamily | | mb . IsFamilyOrAssembly )
{
modifiers | = Modifiers . Protected ;
}
else if ( assemblyIsPrivate )
{
modifiers | = Modifiers . Private ;
}
// NOTE Java doesn't support non-virtual methods, but we set the Final modifier for
// non-virtual methods to approximate the semantics
if ( ( mb . IsFinal | | ( ! mb . IsVirtual & & ( ( modifiers & Modifiers . Private ) = = 0 ) ) ) & & ! mb . IsStatic & & ! mb . IsConstructor )
{
modifiers | = Modifiers . Final ;
}
if ( mb . IsAbstract )
{
modifiers | = Modifiers . Abstract ;
}
else
{
// Some .NET interfaces (like System._AppDomain) have synchronized methods,
// Java doesn't allow synchronized on an abstract methods, so we ignore it for
// abstract methods.
if ( ( mb . GetMethodImplementationFlags ( ) & MethodImplAttributes . Synchronized ) ! = 0 )
{
modifiers | = Modifiers . Synchronized ;
}
}
if ( mb . IsStatic )
{
modifiers | = Modifiers . Static ;
}
if ( ( mb . Attributes & MethodAttributes . PinvokeImpl ) ! = 0 )
{
modifiers | = Modifiers . Native ;
}
2005-10-01 15:16:11 +04:00
ParameterInfo [ ] parameters = mb . GetParameters ( ) ;
2005-12-07 12:06:32 +03:00
if ( parameters . Length > 0 & & IsDefined ( parameters [ parameters . Length - 1 ] , typeof ( ParamArrayAttribute ) ) )
2005-10-01 15:16:11 +04:00
{
modifiers | = Modifiers . VarArgs ;
}
2006-04-05 12:18:58 +04:00
return new ExModifiers ( modifiers , false ) ;
2003-10-17 12:08:31 +04:00
}
2003-05-30 16:08:59 +04:00
2006-04-05 12:18:58 +04:00
internal static ExModifiers GetModifiers ( FieldInfo fi , bool assemblyIsPrivate )
2003-05-30 16:08:59 +04:00
{
2005-12-07 12:06:32 +03:00
#if WHIDBEY
2005-12-19 18:12:49 +03:00
if ( JVM . IsStaticCompiler | | JVM . IsIkvmStub )
2005-12-07 12:06:32 +03:00
{
foreach ( CustomAttributeData cad in CustomAttributeData . GetCustomAttributes ( fi ) )
{
if ( cad . Constructor . DeclaringType = = typeofModifiersAttribute )
{
IList < CustomAttributeTypedArgument > args = cad . ConstructorArguments ;
2006-04-05 12:18:58 +04:00
if ( args . Count = = 2 )
{
return new ExModifiers ( ( Modifiers ) args [ 0 ] . Value , ( bool ) args [ 1 ] . Value ) ;
}
return new ExModifiers ( ( Modifiers ) args [ 0 ] . Value , false ) ;
2005-12-07 12:06:32 +03:00
}
}
}
else
#endif
2005-06-01 13:49:30 +04:00
{
2005-12-07 12:06:32 +03:00
object [ ] customAttribute = fi . GetCustomAttributes ( typeof ( ModifiersAttribute ) , false ) ;
if ( customAttribute . Length = = 1 )
{
2006-04-05 12:18:58 +04:00
ModifiersAttribute mod = ( ModifiersAttribute ) customAttribute [ 0 ] ;
return new ExModifiers ( mod . Modifiers , mod . IsInternal ) ;
2005-12-07 12:06:32 +03:00
}
2005-06-01 13:49:30 +04:00
}
Modifiers modifiers = 0 ;
if ( fi . IsPublic )
{
modifiers | = Modifiers . Public ;
}
else if ( fi . IsPrivate )
{
modifiers | = Modifiers . Private ;
}
else if ( fi . IsFamily | | fi . IsFamilyOrAssembly )
{
modifiers | = Modifiers . Protected ;
}
else if ( assemblyIsPrivate )
{
modifiers | = Modifiers . Private ;
}
if ( fi . IsInitOnly | | fi . IsLiteral )
{
modifiers | = Modifiers . Final ;
}
if ( fi . IsNotSerialized )
{
modifiers | = Modifiers . Transient ;
}
if ( fi . IsStatic )
{
modifiers | = Modifiers . Static ;
}
// TODO reflection doesn't support volatile
2006-04-05 12:18:58 +04:00
return new ExModifiers ( modifiers , false ) ;
2003-05-30 16:08:59 +04:00
}
2005-12-07 12:06:32 +03:00
#if ! COMPACT_FRAMEWORK
2006-04-05 12:18:58 +04:00
internal static void SetModifiers ( MethodBuilder mb , Modifiers modifiers , bool isInternal )
2003-05-30 16:08:59 +04:00
{
2006-04-05 12:18:58 +04:00
CustomAttributeBuilder customAttributeBuilder ;
if ( isInternal )
{
customAttributeBuilder = new CustomAttributeBuilder ( typeofModifiersAttribute . GetConstructor ( new Type [ ] { typeofModifiers , typeof ( bool ) } ) , new object [ ] { modifiers , isInternal } ) ;
}
else
{
customAttributeBuilder = new CustomAttributeBuilder ( typeofModifiersAttribute . GetConstructor ( new Type [ ] { typeofModifiers } ) , new object [ ] { modifiers } ) ;
}
2005-06-01 13:49:30 +04:00
mb . SetCustomAttribute ( customAttributeBuilder ) ;
2003-05-30 16:08:59 +04:00
}
2006-04-05 12:18:58 +04:00
internal static void SetModifiers ( ConstructorBuilder cb , Modifiers modifiers , bool isInternal )
2003-10-17 12:08:31 +04:00
{
2006-04-05 12:18:58 +04:00
CustomAttributeBuilder customAttributeBuilder ;
if ( isInternal )
{
customAttributeBuilder = new CustomAttributeBuilder ( typeofModifiersAttribute . GetConstructor ( new Type [ ] { typeofModifiers , typeof ( bool ) } ) , new object [ ] { modifiers , isInternal } ) ;
}
else
{
customAttributeBuilder = new CustomAttributeBuilder ( typeofModifiersAttribute . GetConstructor ( new Type [ ] { typeofModifiers } ) , new object [ ] { modifiers } ) ;
}
2005-06-01 13:49:30 +04:00
cb . SetCustomAttribute ( customAttributeBuilder ) ;
2003-10-17 12:08:31 +04:00
}
2006-04-05 12:18:58 +04:00
internal static void SetModifiers ( FieldBuilder fb , Modifiers modifiers , bool isInternal )
2003-05-30 16:08:59 +04:00
{
2006-04-05 12:18:58 +04:00
CustomAttributeBuilder customAttributeBuilder ;
if ( isInternal )
{
customAttributeBuilder = new CustomAttributeBuilder ( typeofModifiersAttribute . GetConstructor ( new Type [ ] { typeofModifiers , typeof ( bool ) } ) , new object [ ] { modifiers , isInternal } ) ;
}
else
{
customAttributeBuilder = new CustomAttributeBuilder ( typeofModifiersAttribute . GetConstructor ( new Type [ ] { typeofModifiers } ) , new object [ ] { modifiers } ) ;
}
2005-06-01 13:49:30 +04:00
fb . SetCustomAttribute ( customAttributeBuilder ) ;
2003-05-30 16:08:59 +04:00
}
2005-06-01 13:49:30 +04:00
2006-04-05 12:18:58 +04:00
internal static void SetModifiers ( TypeBuilder tb , Modifiers modifiers , bool isInternal )
2003-05-30 16:08:59 +04:00
{
2006-04-05 12:18:58 +04:00
CustomAttributeBuilder customAttributeBuilder ;
if ( isInternal )
{
customAttributeBuilder = new CustomAttributeBuilder ( typeofModifiersAttribute . GetConstructor ( new Type [ ] { typeofModifiers , typeof ( bool ) } ) , new object [ ] { modifiers , isInternal } ) ;
}
else
{
customAttributeBuilder = new CustomAttributeBuilder ( typeofModifiersAttribute . GetConstructor ( new Type [ ] { typeofModifiers } ) , new object [ ] { modifiers } ) ;
}
2005-06-01 13:49:30 +04:00
tb . SetCustomAttribute ( customAttributeBuilder ) ;
2003-05-30 16:08:59 +04:00
}
2005-06-01 13:49:30 +04:00
internal static void SetNameSig ( MethodBase mb , string name , string sig )
2003-07-24 11:29:51 +04:00
{
2005-12-07 12:06:32 +03:00
CustomAttributeBuilder customAttributeBuilder = new CustomAttributeBuilder ( typeofNameSigAttribute . GetConstructor ( new Type [ ] { typeof ( string ) , typeof ( string ) } ) , new object [ ] { name , sig } ) ;
2005-06-01 13:49:30 +04:00
MethodBuilder method = mb as MethodBuilder ;
if ( method ! = null )
2004-05-14 13:31:54 +04:00
{
2005-06-01 13:49:30 +04:00
method . SetCustomAttribute ( customAttributeBuilder ) ;
2004-05-14 13:31:54 +04:00
}
2005-06-01 13:49:30 +04:00
else
2004-05-14 13:31:54 +04:00
{
2005-06-01 13:49:30 +04:00
( ( ConstructorBuilder ) mb ) . SetCustomAttribute ( customAttributeBuilder ) ;
2004-05-14 13:31:54 +04:00
}
2003-08-05 18:07:22 +04:00
}
2003-07-24 11:29:51 +04:00
2005-06-01 13:49:30 +04:00
internal static void SetNameSig ( FieldBuilder fb , string name , string sig )
2003-12-24 14:51:41 +03:00
{
2005-12-07 12:06:32 +03:00
CustomAttributeBuilder customAttributeBuilder = new CustomAttributeBuilder ( typeofNameSigAttribute . GetConstructor ( new Type [ ] { typeof ( string ) , typeof ( string ) } ) , new object [ ] { name , sig } ) ;
2005-06-01 13:49:30 +04:00
fb . SetCustomAttribute ( customAttributeBuilder ) ;
2003-12-24 14:51:41 +03:00
}
2005-06-01 13:49:30 +04:00
internal static byte [ ] FreezeDryType ( Type type )
2003-05-30 16:08:59 +04:00
{
2005-06-01 13:49:30 +04:00
System . IO . MemoryStream mem = new System . IO . MemoryStream ( ) ;
System . IO . BinaryWriter bw = new System . IO . BinaryWriter ( mem , System . Text . UTF8Encoding . UTF8 ) ;
bw . Write ( ( short ) 1 ) ;
bw . Write ( type . FullName ) ;
bw . Write ( ( short ) 0 ) ;
return mem . ToArray ( ) ;
2003-05-30 16:08:59 +04:00
}
2005-06-01 13:49:30 +04:00
2005-07-07 15:24:08 +04:00
internal static void SetInnerClass ( TypeBuilder typeBuilder , string innerClass , Modifiers modifiers )
2003-05-30 16:08:59 +04:00
{
2005-12-07 12:06:32 +03:00
Type [ ] argTypes = new Type [ ] { typeof ( string ) , typeofModifiers } ;
2005-07-07 15:24:08 +04:00
object [ ] args = new object [ ] { innerClass , modifiers } ;
2005-12-07 12:06:32 +03:00
ConstructorInfo ci = typeofInnerClassAttribute . GetConstructor ( argTypes ) ;
2005-06-01 13:49:30 +04:00
CustomAttributeBuilder customAttributeBuilder = new CustomAttributeBuilder ( ci , args ) ;
typeBuilder . SetCustomAttribute ( customAttributeBuilder ) ;
2003-05-30 16:08:59 +04:00
}
2005-06-01 13:49:30 +04:00
2005-12-07 12:06:32 +03:00
internal static void SetJavaModule ( ModuleBuilder moduleBuilder )
{
CustomAttributeBuilder ikvmModuleAttr = new CustomAttributeBuilder ( typeofJavaModuleAttribute . GetConstructor ( Type . EmptyTypes ) , new object [ 0 ] ) ;
moduleBuilder . SetCustomAttribute ( ikvmModuleAttr ) ;
}
2005-06-01 13:49:30 +04:00
internal static void SetSourceFile ( TypeBuilder typeBuilder , string filename )
2003-05-30 16:08:59 +04:00
{
2005-06-01 13:49:30 +04:00
if ( sourceFileAttribute = = null )
2003-08-21 14:06:34 +04:00
{
2005-12-07 12:06:32 +03:00
sourceFileAttribute = typeofSourceFileAttribute . GetConstructor ( new Type [ ] { typeof ( string ) } ) ;
2003-08-21 14:06:34 +04:00
}
2005-06-01 13:49:30 +04:00
typeBuilder . SetCustomAttribute ( new CustomAttributeBuilder ( sourceFileAttribute , new object [ ] { filename } ) ) ;
2003-05-30 16:08:59 +04:00
}
2005-12-07 12:06:32 +03:00
internal static void SetSourceFile ( ModuleBuilder moduleBuilder , string filename )
{
if ( sourceFileAttribute = = null )
{
sourceFileAttribute = typeofSourceFileAttribute . GetConstructor ( new Type [ ] { typeof ( string ) } ) ;
}
moduleBuilder . SetCustomAttribute ( new CustomAttributeBuilder ( sourceFileAttribute , new object [ ] { filename } ) ) ;
}
2005-08-22 16:42:02 +04:00
internal static void SetLineNumberTable ( MethodBase mb , IKVM . Attributes . LineNumberTableAttribute . LineNumberWriter writer )
2003-05-30 16:08:59 +04:00
{
2005-08-22 16:42:02 +04:00
object arg ;
ConstructorInfo con ;
if ( writer . Count = = 1 )
2005-06-01 13:49:30 +04:00
{
2005-08-22 16:42:02 +04:00
if ( lineNumberTableAttribute2 = = null )
{
2005-12-07 12:06:32 +03:00
lineNumberTableAttribute2 = typeofLineNumberTableAttribute . GetConstructor ( new Type [ ] { typeof ( ushort ) } ) ;
2005-08-22 16:42:02 +04:00
}
con = lineNumberTableAttribute2 ;
arg = ( ushort ) writer . LineNo ;
}
else
{
if ( lineNumberTableAttribute1 = = null )
{
2005-12-07 12:06:32 +03:00
lineNumberTableAttribute1 = typeofLineNumberTableAttribute . GetConstructor ( new Type [ ] { typeof ( byte [ ] ) } ) ;
2005-08-22 16:42:02 +04:00
}
con = lineNumberTableAttribute1 ;
arg = writer . ToArray ( ) ;
2005-06-01 13:49:30 +04:00
}
if ( mb is ConstructorBuilder )
{
2005-08-22 16:42:02 +04:00
( ( ConstructorBuilder ) mb ) . SetCustomAttribute ( new CustomAttributeBuilder ( con , new object [ ] { arg } ) ) ;
2005-06-01 13:49:30 +04:00
}
else
{
2005-08-22 16:42:02 +04:00
( ( MethodBuilder ) mb ) . SetCustomAttribute ( new CustomAttributeBuilder ( con , new object [ ] { arg } ) ) ;
2005-06-01 13:49:30 +04:00
}
2003-05-30 16:08:59 +04:00
}
2005-10-01 15:16:11 +04:00
internal static void SetEnclosingMethodAttribute ( TypeBuilder tb , string className , string methodName , string methodSig )
{
if ( enclosingMethodAttribute = = null )
{
2005-12-07 12:06:32 +03:00
enclosingMethodAttribute = typeofEnclosingMethodAttribute . GetConstructor ( new Type [ ] { typeof ( string ) , typeof ( string ) , typeof ( string ) } ) ;
2005-10-01 15:16:11 +04:00
}
tb . SetCustomAttribute ( new CustomAttributeBuilder ( enclosingMethodAttribute , new object [ ] { className , methodName , methodSig } ) ) ;
}
internal static void SetSignatureAttribute ( TypeBuilder tb , string signature )
{
if ( signatureAttribute = = null )
{
2005-12-07 12:06:32 +03:00
signatureAttribute = typeofSignatureAttribute . GetConstructor ( new Type [ ] { typeof ( string ) } ) ;
2005-10-01 15:16:11 +04:00
}
tb . SetCustomAttribute ( new CustomAttributeBuilder ( signatureAttribute , new object [ ] { signature } ) ) ;
}
internal static void SetSignatureAttribute ( FieldBuilder fb , string signature )
{
if ( signatureAttribute = = null )
{
2005-12-07 12:06:32 +03:00
signatureAttribute = typeofSignatureAttribute . GetConstructor ( new Type [ ] { typeof ( string ) } ) ;
2005-10-01 15:16:11 +04:00
}
fb . SetCustomAttribute ( new CustomAttributeBuilder ( signatureAttribute , new object [ ] { signature } ) ) ;
}
internal static void SetSignatureAttribute ( MethodBase mb , string signature )
{
if ( signatureAttribute = = null )
{
2005-12-07 12:06:32 +03:00
signatureAttribute = typeofSignatureAttribute . GetConstructor ( new Type [ ] { typeof ( string ) } ) ;
2005-10-01 15:16:11 +04:00
}
if ( mb is ConstructorBuilder )
{
( ( ConstructorBuilder ) mb ) . SetCustomAttribute ( new CustomAttributeBuilder ( signatureAttribute , new object [ ] { signature } ) ) ;
}
else
{
( ( MethodBuilder ) mb ) . SetCustomAttribute ( new CustomAttributeBuilder ( signatureAttribute , new object [ ] { signature } ) ) ;
}
}
internal static void SetParamArrayAttribute ( ParameterBuilder pb )
{
if ( paramArrayAttribute = = null )
{
paramArrayAttribute = new CustomAttributeBuilder ( typeof ( ParamArrayAttribute ) . GetConstructor ( Type . EmptyTypes ) , new object [ 0 ] ) ;
}
pb . SetCustomAttribute ( paramArrayAttribute ) ;
}
2005-12-07 12:06:32 +03:00
#endif
internal static NameSigAttribute GetNameSig ( FieldInfo field )
{
#if WHIDBEY
2005-12-19 18:12:49 +03:00
if ( JVM . IsStaticCompiler | | JVM . IsIkvmStub )
2005-12-07 12:06:32 +03:00
{
foreach ( CustomAttributeData cad in CustomAttributeData . GetCustomAttributes ( field ) )
{
if ( cad . Constructor . DeclaringType = = typeofNameSigAttribute )
{
IList < CustomAttributeTypedArgument > args = cad . ConstructorArguments ;
return new NameSigAttribute ( ( string ) args [ 0 ] . Value , ( string ) args [ 1 ] . Value ) ;
}
}
return null ;
}
#endif
object [ ] attr = field . GetCustomAttributes ( typeof ( NameSigAttribute ) , false ) ;
return attr . Length = = 1 ? ( NameSigAttribute ) attr [ 0 ] : null ;
}
internal static NameSigAttribute GetNameSig ( MethodBase method )
{
#if WHIDBEY
2005-12-19 18:12:49 +03:00
if ( JVM . IsStaticCompiler | | JVM . IsIkvmStub )
2005-12-07 12:06:32 +03:00
{
foreach ( CustomAttributeData cad in CustomAttributeData . GetCustomAttributes ( method ) )
{
if ( cad . Constructor . DeclaringType = = typeofNameSigAttribute )
{
IList < CustomAttributeTypedArgument > args = cad . ConstructorArguments ;
return new NameSigAttribute ( ( string ) args [ 0 ] . Value , ( string ) args [ 1 ] . Value ) ;
}
}
return null ;
}
#endif
object [ ] attr = method . GetCustomAttributes ( typeof ( NameSigAttribute ) , false ) ;
return attr . Length = = 1 ? ( NameSigAttribute ) attr [ 0 ] : null ;
}
#if WHIDBEY & & ! COMPACT_FRAMEWORK
2005-12-19 18:12:49 +03:00
internal static T [ ] DecodeArray < T > ( CustomAttributeTypedArgument arg )
2005-12-07 12:06:32 +03:00
{
IList < CustomAttributeTypedArgument > elems = ( IList < CustomAttributeTypedArgument > ) arg . Value ;
T [ ] arr = new T [ elems . Count ] ;
for ( int i = 0 ; i < arr . Length ; i + + )
{
arr [ i ] = ( T ) elems [ i ] . Value ;
}
return arr ;
}
#endif
internal static ImplementsAttribute GetImplements ( Type type )
{
#if WHIDBEY & & ! COMPACT_FRAMEWORK
2005-12-19 18:12:49 +03:00
if ( JVM . IsStaticCompiler | | JVM . IsIkvmStub )
2005-12-07 12:06:32 +03:00
{
foreach ( CustomAttributeData cad in CustomAttributeData . GetCustomAttributes ( type ) )
{
if ( cad . Constructor . DeclaringType = = typeofImplementsAttribute )
{
IList < CustomAttributeTypedArgument > args = cad . ConstructorArguments ;
return new ImplementsAttribute ( DecodeArray < string > ( args [ 0 ] ) ) ;
}
}
return null ;
}
#endif
object [ ] attribs = type . GetCustomAttributes ( typeof ( ImplementsAttribute ) , false ) ;
return attribs . Length = = 1 ? ( ImplementsAttribute ) attribs [ 0 ] : null ;
}
internal static InnerClassAttribute GetInnerClass ( Type type )
{
#if WHIDBEY & & ! COMPACT_FRAMEWORK
2005-12-19 18:12:49 +03:00
if ( JVM . IsStaticCompiler | | JVM . IsIkvmStub )
2005-12-07 12:06:32 +03:00
{
foreach ( CustomAttributeData cad in CustomAttributeData . GetCustomAttributes ( type ) )
{
if ( cad . Constructor . DeclaringType = = typeofInnerClassAttribute )
{
IList < CustomAttributeTypedArgument > args = cad . ConstructorArguments ;
return new InnerClassAttribute ( ( string ) args [ 0 ] . Value , ( Modifiers ) args [ 1 ] . Value ) ;
}
}
return null ;
}
#endif
object [ ] attribs = type . GetCustomAttributes ( typeof ( InnerClassAttribute ) , false ) ;
return attribs . Length = = 1 ? ( InnerClassAttribute ) attribs [ 0 ] : null ;
}
internal static RemappedInterfaceMethodAttribute [ ] GetRemappedInterfaceMethods ( Type type )
{
#if WHIDBEY & & ! COMPACT_FRAMEWORK
2005-12-19 18:12:49 +03:00
if ( JVM . IsStaticCompiler | | JVM . IsIkvmStub )
2005-12-07 12:06:32 +03:00
{
List < RemappedInterfaceMethodAttribute > attrs = new List < RemappedInterfaceMethodAttribute > ( ) ;
foreach ( CustomAttributeData cad in CustomAttributeData . GetCustomAttributes ( type ) )
{
if ( cad . Constructor . DeclaringType = = typeofRemappedInterfaceMethodAttribute )
{
IList < CustomAttributeTypedArgument > args = cad . ConstructorArguments ;
attrs . Add ( new RemappedInterfaceMethodAttribute ( ( string ) args [ 0 ] . Value , ( string ) args [ 1 ] . Value ) ) ;
}
}
return attrs . ToArray ( ) ;
}
#endif
object [ ] attr = type . GetCustomAttributes ( typeof ( RemappedInterfaceMethodAttribute ) , false ) ;
RemappedInterfaceMethodAttribute [ ] attr1 = new RemappedInterfaceMethodAttribute [ attr . Length ] ;
Array . Copy ( attr , attr1 , attr . Length ) ;
return attr1 ;
}
internal static RemappedTypeAttribute GetRemappedType ( Type type )
{
#if WHIDBEY & & ! COMPACT_FRAMEWORK
2005-12-19 18:12:49 +03:00
if ( JVM . IsStaticCompiler | | JVM . IsIkvmStub )
2005-12-07 12:06:32 +03:00
{
foreach ( CustomAttributeData cad in CustomAttributeData . GetCustomAttributes ( type ) )
{
if ( cad . Constructor . DeclaringType = = typeofRemappedTypeAttribute )
{
IList < CustomAttributeTypedArgument > args = cad . ConstructorArguments ;
return new RemappedTypeAttribute ( ( Type ) args [ 0 ] . Value ) ;
}
}
return null ;
}
#endif
object [ ] attribs = type . GetCustomAttributes ( typeof ( RemappedTypeAttribute ) , false ) ;
return attribs . Length = = 1 ? ( RemappedTypeAttribute ) attribs [ 0 ] : null ;
}
internal static RemappedClassAttribute [ ] GetRemappedClasses ( Assembly coreAssembly )
{
#if WHIDBEY & & ! COMPACT_FRAMEWORK
if ( JVM . IsStaticCompiler )
{
List < RemappedClassAttribute > attrs = new List < RemappedClassAttribute > ( ) ;
foreach ( CustomAttributeData cad in CustomAttributeData . GetCustomAttributes ( coreAssembly ) )
{
if ( cad . Constructor . DeclaringType = = typeofRemappedClassAttribute )
{
IList < CustomAttributeTypedArgument > args = cad . ConstructorArguments ;
attrs . Add ( new RemappedClassAttribute ( ( string ) args [ 0 ] . Value , ( Type ) args [ 1 ] . Value ) ) ;
}
}
return attrs . ToArray ( ) ;
}
#endif
object [ ] attr = coreAssembly . GetCustomAttributes ( typeof ( RemappedClassAttribute ) , false ) ;
RemappedClassAttribute [ ] attr1 = new RemappedClassAttribute [ attr . Length ] ;
Array . Copy ( attr , attr1 , attr . Length ) ;
return attr1 ;
}
2006-04-11 18:59:43 +04:00
internal static string GetAnnotationAttributeType ( Type type )
{
object [ ] attr = type . GetCustomAttributes ( typeof ( AnnotationAttributeAttribute ) , false ) ;
if ( attr . Length = = 1 )
{
return ( ( AnnotationAttributeAttribute ) attr [ 0 ] ) . AttributeType ;
}
return null ;
}
2005-12-07 12:06:32 +03:00
internal static bool IsDefined ( Module mod , Type attribute )
{
#if WHIDBEY & & ! COMPACT_FRAMEWORK
2005-12-19 18:12:49 +03:00
if ( JVM . IsStaticCompiler | | JVM . IsIkvmStub )
2005-12-07 12:06:32 +03:00
{
foreach ( CustomAttributeData cad in CustomAttributeData . GetCustomAttributes ( mod ) )
{
// NOTE we don't support subtyping relations!
if ( cad . Constructor . DeclaringType = = attribute )
{
return true ;
}
}
return false ;
}
#endif
return mod . IsDefined ( attribute , false ) ;
}
internal static bool IsDefined ( Assembly asm , Type attribute )
{
#if WHIDBEY & & ! COMPACT_FRAMEWORK
2005-12-19 18:12:49 +03:00
if ( JVM . IsStaticCompiler | | JVM . IsIkvmStub )
2005-12-07 12:06:32 +03:00
{
foreach ( CustomAttributeData cad in CustomAttributeData . GetCustomAttributes ( asm ) )
{
if ( cad . Constructor . DeclaringType = = attribute )
{
return true ;
}
}
return false ;
}
#endif
return asm . IsDefined ( attribute , false ) ;
}
internal static bool IsDefined ( Type type , Type attribute )
{
#if WHIDBEY & & ! COMPACT_FRAMEWORK
2005-12-19 18:12:49 +03:00
if ( JVM . IsStaticCompiler | | JVM . IsIkvmStub )
2005-12-07 12:06:32 +03:00
{
foreach ( CustomAttributeData cad in CustomAttributeData . GetCustomAttributes ( type ) )
{
// NOTE we don't support subtyping relations!
if ( cad . Constructor . DeclaringType = = attribute )
{
return true ;
}
}
return false ;
}
#endif
return type . IsDefined ( attribute , false ) ;
}
internal static bool IsDefined ( ParameterInfo pi , Type attribute )
{
#if WHIDBEY & & ! COMPACT_FRAMEWORK
2005-12-19 18:12:49 +03:00
if ( JVM . IsStaticCompiler | | JVM . IsIkvmStub )
2005-12-07 12:06:32 +03:00
{
foreach ( CustomAttributeData cad in CustomAttributeData . GetCustomAttributes ( pi ) )
{
// NOTE we don't support subtyping relations!
if ( cad . Constructor . DeclaringType = = attribute )
{
return true ;
}
}
return false ;
}
#endif
return pi . IsDefined ( attribute , false ) ;
}
internal static bool IsDefined ( MemberInfo member , Type attribute )
{
#if WHIDBEY & & ! COMPACT_FRAMEWORK
2005-12-19 18:12:49 +03:00
if ( JVM . IsStaticCompiler | | JVM . IsIkvmStub )
2005-12-07 12:06:32 +03:00
{
foreach ( CustomAttributeData cad in CustomAttributeData . GetCustomAttributes ( member ) )
{
// NOTE we don't support subtyping relations!
if ( cad . Constructor . DeclaringType = = attribute )
{
return true ;
}
}
return false ;
}
#endif
return member . IsDefined ( attribute , false ) ;
}
internal static bool IsJavaModule ( Module mod )
{
return IsDefined ( mod , typeofJavaModuleAttribute ) ;
}
internal static bool IsNoPackagePrefix ( Type type )
{
return IsDefined ( type , typeofNoPackagePrefixAttribute ) | | IsDefined ( type . Assembly , typeofNoPackagePrefixAttribute ) ;
}
#if ! COMPACT_FRAMEWORK
internal static void SetRemappedClass ( AssemblyBuilder assemblyBuilder , string name , Type shadowType )
{
ConstructorInfo remappedClassAttribute = typeofRemappedClassAttribute . GetConstructor ( new Type [ ] { typeof ( string ) , typeof ( Type ) } ) ;
assemblyBuilder . SetCustomAttribute ( new CustomAttributeBuilder ( remappedClassAttribute , new object [ ] { name , shadowType } ) ) ;
}
internal static void SetRemappedType ( TypeBuilder typeBuilder , Type shadowType )
{
ConstructorInfo remappedTypeAttribute = typeofRemappedTypeAttribute . GetConstructor ( new Type [ ] { typeof ( Type ) } ) ;
typeBuilder . SetCustomAttribute ( new CustomAttributeBuilder ( remappedTypeAttribute , new object [ ] { shadowType } ) ) ;
}
internal static void SetRemappedInterfaceMethod ( TypeBuilder typeBuilder , string name , string mappedTo )
{
CustomAttributeBuilder cab = new CustomAttributeBuilder ( typeofRemappedInterfaceMethodAttribute . GetConstructor ( new Type [ ] { typeof ( string ) , typeof ( string ) } ) , new object [ ] { name , mappedTo } ) ;
typeBuilder . SetCustomAttribute ( cab ) ;
}
internal static void SetExceptionIsUnsafeForMapping ( TypeBuilder typeBuilder )
{
CustomAttributeBuilder cab = new CustomAttributeBuilder ( typeofExceptionIsUnsafeForMappingAttribute . GetConstructor ( Type . EmptyTypes ) , new object [ 0 ] ) ;
typeBuilder . SetCustomAttribute ( cab ) ;
}
internal static void SetConstantValue ( FieldBuilder field , object constantValue )
{
CustomAttributeBuilder constantValueAttrib = new CustomAttributeBuilder ( typeofConstantValueAttribute . GetConstructor ( new Type [ ] { constantValue . GetType ( ) } ) , new object [ ] { constantValue } ) ;
field . SetCustomAttribute ( constantValueAttrib ) ;
}
#endif
2003-05-30 16:08:59 +04:00
}
2005-12-07 12:06:32 +03:00
#if ! COMPACT_FRAMEWORK
2005-11-01 17:01:42 +03:00
abstract class Annotation
{
internal abstract void Apply ( TypeBuilder tb , object annotation ) ;
}
2005-12-07 12:06:32 +03:00
#endif
2005-11-01 17:01:42 +03:00
2006-04-05 12:18:58 +04:00
[Flags]
enum TypeFlags : ushort
{
HasIncompleteInterfaceImplementation = 1 ,
InternalAccess = 2 ,
HasStaticInitializer = 4
}
2006-04-10 13:09:09 +04:00
internal abstract class TypeWrapper
2003-05-30 16:08:59 +04:00
{
2005-06-01 13:49:30 +04:00
private readonly string name ; // java name (e.g. java.lang.Object)
private readonly Modifiers modifiers ;
2006-04-05 12:18:58 +04:00
private TypeFlags flags ;
2005-06-01 13:49:30 +04:00
private MethodWrapper [ ] methods ;
private FieldWrapper [ ] fields ;
private readonly TypeWrapper baseWrapper ;
2006-04-10 13:09:09 +04:00
#if ! STATIC_COMPILER
2006-03-23 14:57:41 +03:00
private object classObject ;
2006-04-10 13:09:09 +04:00
#endif
2005-06-01 13:49:30 +04:00
internal static readonly TypeWrapper [ ] EmptyArray = new TypeWrapper [ 0 ] ;
internal const Modifiers UnloadableModifiersHack = Modifiers . Final | Modifiers . Interface | Modifiers . Private ;
internal const Modifiers VerifierTypeModifiersHack = Modifiers . Final | Modifiers . Interface ;
2003-07-31 16:49:29 +04:00
2006-03-23 14:57:41 +03:00
internal TypeWrapper ( Modifiers modifiers , string name , TypeWrapper baseWrapper )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
Profiler . Count ( "TypeWrapper" ) ;
// class name should be dotted or null for primitives
Debug . Assert ( name = = null | | name . IndexOf ( '/' ) < 0 ) ;
2003-08-01 16:12:08 +04:00
2005-06-01 13:49:30 +04:00
this . modifiers = modifiers ;
2005-07-20 13:42:11 +04:00
this . name = name = = null ? null : String . Intern ( name ) ;
2005-06-01 13:49:30 +04:00
this . baseWrapper = baseWrapper ;
2006-03-23 14:57:41 +03:00
}
2006-04-10 13:09:09 +04:00
#if ! STATIC_COMPILER
2006-03-23 14:57:41 +03:00
internal void SetClassObject ( object classObject )
{
this . classObject = classObject ;
2004-10-19 17:43:55 +04:00
}
2005-06-01 13:49:30 +04:00
internal object ClassObject
2004-10-19 17:43:55 +04:00
{
2005-06-01 13:49:30 +04:00
get
{
2006-03-23 14:57:41 +03:00
Debug . Assert ( ! IsUnloadable & & ! IsVerifierType & & ! JVM . IsStaticCompiler ) ;
lock ( this )
{
if ( classObject = = null )
{
// DynamicTypeWrapper should haved already had SetClassObject explicitly
Debug . Assert ( ! ( this is DynamicTypeWrapper ) ) ;
classObject = JVM . Library . newClass ( this , null ) ;
}
}
2005-06-01 13:49:30 +04:00
return classObject ;
}
2004-10-19 17:43:55 +04:00
}
2003-05-13 00:00:15 +04:00
2006-03-27 17:59:59 +04:00
internal static TypeWrapper FromClass ( object classObject )
{
return ( TypeWrapper ) JVM . Library . getWrapperFromClass ( classObject ) ;
}
2006-04-10 13:09:09 +04:00
#endif // !STATIC_COMPILER
2006-03-27 17:59:59 +04:00
2005-06-01 13:49:30 +04:00
public override string ToString ( )
2004-12-21 17:59:29 +03:00
{
2005-06-01 13:49:30 +04:00
return GetType ( ) . Name + "[" + name + "]" ;
2004-12-21 17:59:29 +03:00
}
2005-06-01 13:49:30 +04:00
// For UnloadableTypeWrapper it tries to load the type through the specified loader
// and if that fails it throw a NoClassDefFoundError (not a java.lang.NoClassDefFoundError),
// for all other types this is a no-op.
internal virtual TypeWrapper EnsureLoadable ( ClassLoaderWrapper loader )
2004-12-21 17:59:29 +03:00
{
2005-06-01 13:49:30 +04:00
return this ;
2004-12-21 17:59:29 +03:00
}
2005-02-23 15:56:15 +03:00
2005-06-01 13:49:30 +04:00
internal bool HasIncompleteInterfaceImplementation
2003-05-13 00:00:15 +04:00
{
2005-06-01 13:49:30 +04:00
get
{
2006-04-05 12:18:58 +04:00
return ( flags & TypeFlags . HasIncompleteInterfaceImplementation ) ! = 0 | | ( baseWrapper ! = null & & baseWrapper . HasIncompleteInterfaceImplementation ) ;
2005-06-01 13:49:30 +04:00
}
set
{
2006-04-05 12:18:58 +04:00
// TODO do we need locking here?
if ( value )
{
flags | = TypeFlags . HasIncompleteInterfaceImplementation ;
}
else
{
flags & = ~ TypeFlags . HasIncompleteInterfaceImplementation ;
}
2005-06-01 13:49:30 +04:00
}
2003-05-13 00:00:15 +04:00
}
2005-06-01 13:49:30 +04:00
internal virtual bool HasStaticInitializer
2004-09-15 17:35:44 +04:00
{
2005-06-01 13:49:30 +04:00
get
{
2006-04-05 12:18:58 +04:00
return ( flags & TypeFlags . HasStaticInitializer ) ! = 0 ;
}
set
{
// TODO do we need locking here?
if ( value )
{
flags | = TypeFlags . HasStaticInitializer ;
}
else
{
flags & = ~ TypeFlags . HasStaticInitializer ;
}
2005-06-01 13:49:30 +04:00
}
2004-09-15 17:35:44 +04:00
}
2005-06-01 13:49:30 +04:00
// a ghost is an interface that appears to be implemented by a .NET type
// (e.g. System.String (aka java.lang.String) appears to implement java.lang.CharSequence,
// so java.lang.CharSequence is a ghost)
internal virtual bool IsGhost
2003-07-31 16:49:29 +04:00
{
2005-06-01 13:49:30 +04:00
get
{
return false ;
}
2003-07-31 16:49:29 +04:00
}
2005-06-01 13:49:30 +04:00
// is this an array type of which the ultimate element type is a ghost?
internal bool IsGhostArray
2003-08-12 17:09:31 +04:00
{
2005-06-01 13:49:30 +04:00
get
{
return IsArray & & ( ElementTypeWrapper . IsGhost | | ElementTypeWrapper . IsGhostArray ) ;
}
2003-08-12 17:09:31 +04:00
}
2005-06-01 13:49:30 +04:00
internal virtual FieldInfo GhostRefField
2003-10-17 12:08:31 +04:00
{
2005-06-01 13:49:30 +04:00
get
{
throw new InvalidOperationException ( ) ;
}
2003-10-17 12:08:31 +04:00
}
2005-06-01 13:49:30 +04:00
internal virtual bool IsRemapped
2004-03-08 18:18:47 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
return false ;
}
2004-03-08 18:18:47 +03:00
}
2005-06-01 13:49:30 +04:00
internal bool IsArray
2003-03-21 16:41:43 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
return name ! = null & & name [ 0 ] = = '[' ;
}
2003-03-21 16:41:43 +03:00
}
2005-06-01 13:49:30 +04:00
// NOTE for non-array types this returns 0
internal int ArrayRank
2003-01-06 16:56:37 +03:00
{
2005-06-01 13:49:30 +04:00
get
2003-01-06 16:56:37 +03:00
{
2005-06-01 13:49:30 +04:00
int i = 0 ;
if ( name ! = null )
2003-06-20 17:46:13 +04:00
{
2005-06-01 13:49:30 +04:00
while ( name [ i ] = = '[' )
{
i + + ;
}
2003-06-20 17:46:13 +04:00
}
2005-06-01 13:49:30 +04:00
return i ;
2003-01-06 16:56:37 +03:00
}
}
2005-06-01 13:49:30 +04:00
internal bool IsNonPrimitiveValueType
2003-04-14 13:41:58 +04:00
{
2005-06-01 13:49:30 +04:00
get
{
return this ! = VerifierTypeWrapper . Null & & ! IsPrimitive & & ! IsGhost & & TypeAsTBD . IsValueType ;
}
2003-04-14 13:41:58 +04:00
}
2005-06-01 13:49:30 +04:00
internal bool IsPrimitive
2003-01-06 16:56:37 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
return name = = null ;
}
2003-01-06 16:56:37 +03:00
}
2005-06-01 13:49:30 +04:00
internal bool IsWidePrimitive
2003-11-17 15:01:50 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
return this = = PrimitiveTypeWrapper . LONG | | this = = PrimitiveTypeWrapper . DOUBLE ;
}
2003-11-17 15:01:50 +03:00
}
2005-06-01 13:49:30 +04:00
internal bool IsIntOnStackPrimitive
2003-11-17 15:01:50 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
return name = = null & &
( this = = PrimitiveTypeWrapper . BOOLEAN | |
this = = PrimitiveTypeWrapper . BYTE | |
this = = PrimitiveTypeWrapper . CHAR | |
this = = PrimitiveTypeWrapper . SHORT | |
this = = PrimitiveTypeWrapper . INT ) ;
}
2003-11-17 15:01:50 +03:00
}
2005-06-01 13:49:30 +04:00
internal bool IsUnloadable
2003-01-06 16:56:37 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
// NOTE we abuse modifiers to note unloadable classes
return modifiers = = UnloadableModifiersHack ;
}
2003-01-06 16:56:37 +03:00
}
2005-06-01 13:49:30 +04:00
internal bool IsVerifierType
2003-01-06 16:56:37 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
// NOTE we abuse modifiers to note verifier types
return modifiers = = VerifierTypeModifiersHack ;
}
2003-01-06 16:56:37 +03:00
}
2005-06-01 13:49:30 +04:00
internal virtual bool IsMapUnsafeException
2004-03-08 18:18:47 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
return false ;
}
2004-03-08 18:18:47 +03:00
}
2005-06-01 13:49:30 +04:00
internal Modifiers Modifiers
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
return modifiers ;
}
2002-12-18 19:00:25 +03:00
}
2005-06-01 13:49:30 +04:00
// since for inner classes, the modifiers returned by Class.getModifiers are different from the actual
// modifiers (as used by the VM access control mechanism), we have this additional property
internal virtual Modifiers ReflectiveModifiers
2003-05-30 16:08:59 +04:00
{
2005-06-01 13:49:30 +04:00
get
{
return modifiers ;
}
2003-05-30 16:08:59 +04:00
}
2006-04-05 12:18:58 +04:00
internal bool IsInternal
{
get
{
return ( flags & TypeFlags . InternalAccess ) ! = 0 ;
}
set
{
// TODO do we need locking here?
if ( value )
{
flags | = TypeFlags . InternalAccess ;
}
else
{
flags & = ~ TypeFlags . InternalAccess ;
}
}
}
2005-06-01 13:49:30 +04:00
internal bool IsPublic
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
return ( modifiers & Modifiers . Public ) ! = 0 ;
}
2002-12-18 19:00:25 +03:00
}
2005-06-01 13:49:30 +04:00
internal bool IsAbstract
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
// interfaces don't need to marked abstract explicitly (and javac 1.1 didn't do it)
return ( modifiers & ( Modifiers . Abstract | Modifiers . Interface ) ) ! = 0 ;
}
2002-12-18 19:00:25 +03:00
}
2005-06-01 13:49:30 +04:00
internal bool IsFinal
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
return ( modifiers & Modifiers . Final ) ! = 0 ;
}
2002-12-18 19:00:25 +03:00
}
2005-06-01 13:49:30 +04:00
internal bool IsInterface
2003-05-30 16:08:59 +04:00
{
2005-06-01 13:49:30 +04:00
get
{
Debug . Assert ( ! IsUnloadable & & ! IsVerifierType ) ;
return ( modifiers & Modifiers . Interface ) ! = 0 ;
}
2003-05-30 16:08:59 +04:00
}
2005-06-01 13:49:30 +04:00
// this exists because interfaces and arrays of interfaces are treated specially
// by the verifier, interfaces don't have a common base (other than java.lang.Object)
// so any object reference or object array reference can be used where an interface
// or interface array reference is expected (the compiler will insert the required casts).
internal bool IsInterfaceOrInterfaceArray
2003-08-29 14:14:08 +04:00
{
2005-06-01 13:49:30 +04:00
get
2003-08-29 14:14:08 +04:00
{
2005-06-01 13:49:30 +04:00
TypeWrapper tw = this ;
while ( tw . IsArray )
{
tw = tw . ElementTypeWrapper ;
}
return tw . IsInterface ;
2003-08-29 14:14:08 +04:00
}
}
2006-03-23 14:57:41 +03:00
internal abstract ClassLoaderWrapper GetClassLoader ( ) ;
2002-12-18 19:00:25 +03:00
2005-06-01 13:49:30 +04:00
internal FieldWrapper GetFieldWrapper ( string fieldName , string fieldSig )
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
lock ( this )
{
if ( fields = = null )
{
LazyPublishMembers ( ) ;
}
}
foreach ( FieldWrapper fw in fields )
{
if ( fw . Name = = fieldName & & fw . Signature = = fieldSig )
{
return fw ;
}
}
foreach ( TypeWrapper iface in this . Interfaces )
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
FieldWrapper fw = iface . GetFieldWrapper ( fieldName , fieldSig ) ;
if ( fw ! = null )
{
return fw ;
}
2005-01-03 11:26:21 +03:00
}
2005-06-01 13:49:30 +04:00
if ( baseWrapper ! = null )
{
return baseWrapper . GetFieldWrapper ( fieldName , fieldSig ) ;
}
return null ;
2005-01-03 11:26:21 +03:00
}
2005-06-01 13:49:30 +04:00
protected virtual void LazyPublishMembers ( )
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
if ( methods = = null )
{
methods = MethodWrapper . EmptyArray ;
}
if ( fields = = null )
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
fields = FieldWrapper . EmptyArray ;
}
2005-01-03 11:26:21 +03:00
}
2005-06-01 13:49:30 +04:00
internal MethodWrapper [ ] GetMethods ( )
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
lock ( this )
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
if ( methods = = null )
{
LazyPublishMembers ( ) ;
}
2002-12-18 19:00:25 +03:00
}
2005-06-01 13:49:30 +04:00
return methods ;
2005-01-03 11:26:21 +03:00
}
2005-06-01 13:49:30 +04:00
internal FieldWrapper [ ] GetFields ( )
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
lock ( this )
{
if ( fields = = null )
{
LazyPublishMembers ( ) ;
}
}
return fields ;
2005-01-03 11:26:21 +03:00
}
2005-06-01 13:49:30 +04:00
internal MethodWrapper GetMethodWrapper ( string name , string sig , bool inherit )
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
lock ( this )
{
if ( methods = = null )
{
LazyPublishMembers ( ) ;
}
}
foreach ( MethodWrapper mw in methods )
{
if ( mw . Name = = name & & mw . Signature = = sig )
{
return mw ;
}
}
if ( inherit & & baseWrapper ! = null )
{
return baseWrapper . GetMethodWrapper ( name , sig , inherit ) ;
}
return null ;
2005-01-03 11:26:21 +03:00
}
2005-06-01 13:49:30 +04:00
internal void SetMethods ( MethodWrapper [ ] methods )
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
Debug . Assert ( methods ! = null ) ;
this . methods = methods ;
2002-12-18 19:00:25 +03:00
}
2005-06-01 13:49:30 +04:00
internal void SetFields ( FieldWrapper [ ] fields )
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
Debug . Assert ( fields ! = null ) ;
this . fields = fields ;
2005-01-03 11:26:21 +03:00
}
2002-12-18 19:00:25 +03:00
2005-06-01 13:49:30 +04:00
internal string Name
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
get
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
return name ;
2005-01-03 11:26:21 +03:00
}
}
2002-12-18 19:00:25 +03:00
2005-06-01 13:49:30 +04:00
// the name of the type as it appears in a Java signature string (e.g. "Ljava.lang.Object;" or "I")
internal virtual string SigName
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
get
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
return "L" + this . Name + ";" ;
2005-01-03 11:26:21 +03:00
}
}
2005-06-01 13:49:30 +04:00
internal abstract Assembly Assembly
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
get ;
2005-01-03 11:26:21 +03:00
}
2005-06-01 13:49:30 +04:00
// returns true iff wrapper is allowed to access us
internal bool IsAccessibleFrom ( TypeWrapper wrapper )
2005-01-03 11:26:21 +03:00
{
2006-04-05 12:18:58 +04:00
return IsPublic
| | ( IsInternal & & this . Assembly = = wrapper . Assembly )
| | IsInSamePackageAs ( wrapper ) ;
2002-12-18 19:00:25 +03:00
}
2005-06-01 13:49:30 +04:00
internal bool IsInSamePackageAs ( TypeWrapper wrapper )
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
if ( GetClassLoader ( ) = = wrapper . GetClassLoader ( ) & &
// Both types must also be in the same assembly, otherwise
// the packages are not accessible.
wrapper . Assembly = = this . Assembly )
{
int index1 = name . LastIndexOf ( '.' ) ;
int index2 = wrapper . name . LastIndexOf ( '.' ) ;
if ( index1 = = - 1 & & index2 = = - 1 )
{
return true ;
}
// for array types we need to skip the brackets
int skip1 = 0 ;
int skip2 = 0 ;
while ( name [ skip1 ] = = '[' )
{
skip1 + + ;
}
while ( wrapper . name [ skip2 ] = = '[' )
{
skip2 + + ;
}
if ( skip1 > 0 )
{
// skip over the L that follows the brackets
skip1 + + ;
}
if ( skip2 > 0 )
{
// skip over the L that follows the brackets
skip2 + + ;
}
if ( ( index1 - skip1 ) ! = ( index2 - skip2 ) )
{
return false ;
}
return String . CompareOrdinal ( name , skip1 , wrapper . name , skip2 , index1 - skip1 ) = = 0 ;
}
return false ;
2002-12-18 19:00:25 +03:00
}
2005-06-01 13:49:30 +04:00
internal abstract Type TypeAsTBD
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
get ;
2003-08-21 14:06:34 +04:00
}
2005-12-07 12:06:32 +03:00
#if ! COMPACT_FRAMEWORK
2005-06-01 13:49:30 +04:00
internal virtual TypeBuilder TypeAsBuilder
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
get
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
TypeBuilder typeBuilder = TypeAsTBD as TypeBuilder ;
Debug . Assert ( typeBuilder ! = null ) ;
return typeBuilder ;
2002-12-18 19:00:25 +03:00
}
}
2005-12-07 12:06:32 +03:00
#endif
2002-12-18 19:00:25 +03:00
2005-06-01 13:49:30 +04:00
internal Type TypeAsSignatureType
2003-08-12 17:09:31 +04:00
{
2005-06-01 13:49:30 +04:00
get
{
if ( IsUnloadable )
{
return typeof ( object ) ;
}
if ( IsGhostArray )
{
int rank = ArrayRank ;
string type = "System.Object" ;
for ( int i = 0 ; i < rank ; i + + )
{
type + = "[]" ;
}
return Type . GetType ( type , true ) ;
}
return TypeAsTBD ;
}
2003-08-12 17:09:31 +04:00
}
2005-06-01 13:49:30 +04:00
internal virtual Type TypeAsBaseType
2003-10-17 12:08:31 +04:00
{
2005-06-01 13:49:30 +04:00
get
2003-01-06 16:56:37 +03:00
{
2005-06-01 13:49:30 +04:00
return TypeAsTBD ;
2003-01-06 16:56:37 +03:00
}
2005-06-01 13:49:30 +04:00
}
internal Type TypeAsLocalOrStackType
{
get
2003-08-12 17:09:31 +04:00
{
2005-06-01 13:49:30 +04:00
// NOTE as a convenience to the compiler, we replace return address types with typeof(int)
if ( VerifierTypeWrapper . IsRet ( this ) )
{
return typeof ( int ) ;
}
if ( IsUnloadable | | IsGhost )
{
return typeof ( object ) ;
}
if ( IsNonPrimitiveValueType )
{
// return either System.ValueType or System.Enum
return TypeAsTBD . BaseType ;
}
if ( IsGhostArray )
2003-08-12 17:09:31 +04:00
{
2005-06-01 13:49:30 +04:00
int rank = ArrayRank ;
string type = "System.Object" ;
for ( int i = 0 ; i < rank ; i + + )
{
type + = "[]" ;
}
return Type . GetType ( type , true ) ;
2003-08-12 17:09:31 +04:00
}
2005-06-01 13:49:30 +04:00
return TypeAsTBD ;
2003-08-12 17:09:31 +04:00
}
2003-09-10 18:58:19 +04:00
}
2005-06-01 13:49:30 +04:00
/** <summary>Use this if the type is used as an array or array element</summary> */
internal Type TypeAsArrayType
2003-09-10 18:58:19 +04:00
{
2005-06-01 13:49:30 +04:00
get
2003-09-10 18:58:19 +04:00
{
2005-06-01 13:49:30 +04:00
if ( IsUnloadable | | IsGhost )
2003-09-10 18:58:19 +04:00
{
2005-06-01 13:49:30 +04:00
return typeof ( object ) ;
2003-09-10 18:58:19 +04:00
}
2005-06-01 13:49:30 +04:00
if ( IsGhostArray )
{
int rank = ArrayRank ;
string type = "System.Object" ;
for ( int i = 0 ; i < rank ; i + + )
{
type + = "[]" ;
}
return Type . GetType ( type , true ) ;
}
return TypeAsTBD ;
2003-09-10 18:58:19 +04:00
}
}
2005-06-01 13:49:30 +04:00
internal Type TypeAsExceptionType
2003-09-10 18:58:19 +04:00
{
2005-06-01 13:49:30 +04:00
get
2003-10-17 12:08:31 +04:00
{
2005-06-01 13:49:30 +04:00
if ( IsUnloadable )
2003-10-17 12:08:31 +04:00
{
2005-06-01 13:49:30 +04:00
return typeof ( Exception ) ;
2003-10-17 12:08:31 +04:00
}
2005-06-01 13:49:30 +04:00
return TypeAsTBD ;
2003-10-17 12:08:31 +04:00
}
2003-09-10 18:58:19 +04:00
}
2005-06-01 13:49:30 +04:00
internal TypeWrapper BaseTypeWrapper
2003-09-10 18:58:19 +04:00
{
2005-06-01 13:49:30 +04:00
get
2003-09-10 18:58:19 +04:00
{
2005-06-01 13:49:30 +04:00
return baseWrapper ;
2003-09-10 18:58:19 +04:00
}
2003-01-06 16:56:37 +03:00
}
2005-06-01 13:49:30 +04:00
internal TypeWrapper ElementTypeWrapper
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
Debug . Assert ( ! this . IsUnloadable ) ;
Debug . Assert ( this = = VerifierTypeWrapper . Null | | this . IsArray ) ;
if ( this = = VerifierTypeWrapper . Null )
{
return VerifierTypeWrapper . Null ;
}
// TODO consider caching the element type
switch ( name [ 1 ] )
{
case '[' :
// NOTE this call to LoadClassByDottedNameFast can never fail and will not trigger a class load
// (because the ultimate element type was already loaded when this type was created)
2006-03-23 14:57:41 +03:00
return GetClassLoader ( ) . LoadClassByDottedNameFast ( name . Substring ( 1 ) ) ;
2005-06-01 13:49:30 +04:00
case 'L' :
// NOTE this call to LoadClassByDottedNameFast can never fail and will not trigger a class load
// (because the ultimate element type was already loaded when this type was created)
2006-03-23 14:57:41 +03:00
return GetClassLoader ( ) . LoadClassByDottedNameFast ( name . Substring ( 2 , name . Length - 3 ) ) ;
2005-06-01 13:49:30 +04:00
case 'Z' :
return PrimitiveTypeWrapper . BOOLEAN ;
case 'B' :
return PrimitiveTypeWrapper . BYTE ;
case 'S' :
return PrimitiveTypeWrapper . SHORT ;
case 'C' :
return PrimitiveTypeWrapper . CHAR ;
case 'I' :
return PrimitiveTypeWrapper . INT ;
case 'J' :
return PrimitiveTypeWrapper . LONG ;
case 'F' :
return PrimitiveTypeWrapper . FLOAT ;
case 'D' :
return PrimitiveTypeWrapper . DOUBLE ;
default :
throw new InvalidOperationException ( name ) ;
}
}
2002-12-18 19:00:25 +03:00
}
2005-11-01 17:01:42 +03:00
internal virtual TypeWrapper MakeArrayType ( int rank )
2003-01-06 16:56:37 +03:00
{
2005-08-19 13:08:43 +04:00
Debug . Assert ( rank ! = 0 ) ;
2005-06-01 13:49:30 +04:00
// NOTE this call to LoadClassByDottedNameFast can never fail and will not trigger a class load
return GetClassLoader ( ) . LoadClassByDottedNameFast ( new String ( '[' , rank ) + this . SigName ) ;
}
2003-12-24 14:51:41 +03:00
2005-06-01 13:49:30 +04:00
internal bool ImplementsInterface ( TypeWrapper interfaceWrapper )
{
TypeWrapper typeWrapper = this ;
while ( typeWrapper ! = null )
2003-06-13 19:13:20 +04:00
{
2005-06-01 13:49:30 +04:00
TypeWrapper [ ] interfaces = typeWrapper . Interfaces ;
for ( int i = 0 ; i < interfaces . Length ; i + + )
{
if ( interfaces [ i ] = = interfaceWrapper )
{
return true ;
}
if ( interfaces [ i ] . ImplementsInterface ( interfaceWrapper ) )
{
return true ;
}
}
typeWrapper = typeWrapper . BaseTypeWrapper ;
2003-01-06 16:56:37 +03:00
}
2005-06-01 13:49:30 +04:00
return false ;
2003-01-06 16:56:37 +03:00
}
2003-12-24 14:51:41 +03:00
2005-06-01 13:49:30 +04:00
internal bool IsSubTypeOf ( TypeWrapper baseType )
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
// make sure IsSubTypeOf isn't used on primitives
Debug . Assert ( ! this . IsPrimitive ) ;
Debug . Assert ( ! baseType . IsPrimitive ) ;
// can't be used on Unloadable
Debug . Assert ( ! this . IsUnloadable ) ;
Debug . Assert ( ! baseType . IsUnloadable ) ;
if ( baseType . IsInterface )
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
if ( baseType = = this )
2002-12-18 19:00:25 +03:00
{
return true ;
}
2005-06-01 13:49:30 +04:00
return ImplementsInterface ( baseType ) ;
}
// NOTE this isn't just an optimization, it is also required when this is an interface
if ( baseType = = CoreClasses . java . lang . Object . Wrapper )
{
return true ;
}
TypeWrapper subType = this ;
while ( subType ! = baseType )
{
subType = subType . BaseTypeWrapper ;
if ( subType = = null )
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
return false ;
2002-12-18 19:00:25 +03:00
}
}
2005-06-01 13:49:30 +04:00
return true ;
2002-12-18 19:00:25 +03:00
}
2003-01-07 17:53:17 +03:00
2005-06-01 13:49:30 +04:00
internal bool IsAssignableTo ( TypeWrapper wrapper )
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
if ( this = = wrapper )
2002-12-18 19:00:25 +03:00
{
return true ;
}
2005-06-01 13:49:30 +04:00
if ( this . IsPrimitive | | wrapper . IsPrimitive )
2002-12-18 19:00:25 +03:00
{
return false ;
}
2005-06-01 13:49:30 +04:00
if ( this = = VerifierTypeWrapper . Null )
{
return true ;
}
if ( wrapper . IsInterface )
{
return ImplementsInterface ( wrapper ) ;
}
int rank1 = this . ArrayRank ;
int rank2 = wrapper . ArrayRank ;
if ( rank1 > 0 & & rank2 > 0 )
{
rank1 - - ;
rank2 - - ;
TypeWrapper elem1 = this . ElementTypeWrapper ;
TypeWrapper elem2 = wrapper . ElementTypeWrapper ;
while ( rank1 ! = 0 & & rank2 ! = 0 )
{
elem1 = elem1 . ElementTypeWrapper ;
elem2 = elem2 . ElementTypeWrapper ;
rank1 - - ;
rank2 - - ;
}
return ! elem1 . IsNonPrimitiveValueType & & elem1 . IsSubTypeOf ( elem2 ) ;
}
return this . IsSubTypeOf ( wrapper ) ;
2002-12-18 19:00:25 +03:00
}
2005-06-01 13:49:30 +04:00
internal abstract TypeWrapper [ ] Interfaces
2003-01-06 16:56:37 +03:00
{
2005-06-01 13:49:30 +04:00
get ;
2003-01-06 16:56:37 +03:00
}
2005-06-01 13:49:30 +04:00
// NOTE this property can only be called for finished types!
internal abstract TypeWrapper [ ] InnerClasses
2003-01-06 16:56:37 +03:00
{
2005-06-01 13:49:30 +04:00
get ;
2003-01-06 16:56:37 +03:00
}
2005-06-01 13:49:30 +04:00
// NOTE this property can only be called for finished types!
internal abstract TypeWrapper DeclaringTypeWrapper
2004-02-02 12:46:13 +03:00
{
2005-06-01 13:49:30 +04:00
get ;
2004-02-02 12:46:13 +03:00
}
2005-06-01 13:49:30 +04:00
2005-08-05 12:40:54 +04:00
internal abstract void Finish ( ) ;
2004-08-17 13:05:21 +04:00
2005-12-07 12:06:32 +03:00
#if ! COMPACT_FRAMEWORK
2005-06-01 13:49:30 +04:00
private void ImplementInterfaceMethodStubImpl ( MethodWrapper ifmethod , TypeBuilder typeBuilder , DynamicTypeWrapper wrapper )
2003-06-10 17:28:47 +04:00
{
2005-06-01 13:49:30 +04:00
// we're mangling the name to prevent subclasses from accidentally overriding this method and to
// prevent clashes with overloaded method stubs that are erased to the same signature (e.g. unloadable types and ghost arrays)
string mangledName = this . Name + "/" + ifmethod . Name + ifmethod . Signature ;
MethodWrapper mce = null ;
TypeWrapper lookup = wrapper ;
while ( lookup ! = null )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
mce = lookup . GetMethodWrapper ( ifmethod . Name , ifmethod . Signature , true ) ;
if ( mce = = null | | ! mce . IsStatic )
{
break ;
}
lookup = mce . DeclaringType . BaseTypeWrapper ;
2002-12-18 19:00:25 +03:00
}
2005-06-01 13:49:30 +04:00
if ( mce ! = null )
2002-12-18 19:00:25 +03:00
{
2005-08-02 12:44:55 +04:00
if ( mce . DeclaringType ! = wrapper )
{
// check the loader constraints
bool error = false ;
if ( mce . ReturnType ! = ifmethod . ReturnType )
{
// TODO handle unloadable
error = true ;
}
TypeWrapper [ ] mceparams = mce . GetParameters ( ) ;
TypeWrapper [ ] ifparams = ifmethod . GetParameters ( ) ;
for ( int i = 0 ; i < mceparams . Length ; i + + )
{
if ( mceparams [ i ] ! = ifparams [ i ] )
{
// TODO handle unloadable
error = true ;
break ;
}
}
if ( error )
{
2005-09-01 11:34:53 +04:00
MethodBuilder mb = typeBuilder . DefineMethod ( mangledName , MethodAttributes . HideBySig | MethodAttributes . NewSlot | MethodAttributes . Private | MethodAttributes . Virtual | MethodAttributes . Final , ifmethod . ReturnTypeForDefineMethod , ifmethod . GetParametersForDefineMethod ( ) ) ;
2005-08-02 12:44:55 +04:00
AttributeHelper . HideFromJava ( mb ) ;
EmitHelper . Throw ( mb . GetILGenerator ( ) , "java.lang.LinkageError" , wrapper . Name + "." + ifmethod . Name + ifmethod . Signature ) ;
typeBuilder . DefineMethodOverride ( mb , ( MethodInfo ) ifmethod . GetMethod ( ) ) ;
return ;
}
}
2005-06-01 13:49:30 +04:00
if ( mce . IsMirandaMethod & & mce . DeclaringType = = wrapper )
{
// Miranda methods already have a methodimpl (if needed) to implement the correct interface method
}
else if ( ! mce . IsPublic )
{
// NOTE according to the ECMA spec it isn't legal for a privatescope method to be virtual, but this works and
// it makes sense, so I hope the spec is wrong
// UPDATE unfortunately, according to Serge Lidin the spec is correct, and it is not allowed to have virtual privatescope
// methods. Sigh! So I have to use private methods and mangle the name
2005-09-01 11:34:53 +04:00
MethodBuilder mb = typeBuilder . DefineMethod ( mangledName , MethodAttributes . HideBySig | MethodAttributes . NewSlot | MethodAttributes . Private | MethodAttributes . Virtual | MethodAttributes . Final , ifmethod . ReturnTypeForDefineMethod , ifmethod . GetParametersForDefineMethod ( ) ) ;
2005-06-01 13:49:30 +04:00
AttributeHelper . HideFromJava ( mb ) ;
EmitHelper . Throw ( mb . GetILGenerator ( ) , "java.lang.IllegalAccessError" , wrapper . Name + "." + ifmethod . Name + ifmethod . Signature ) ;
typeBuilder . DefineMethodOverride ( mb , ( MethodInfo ) ifmethod . GetMethod ( ) ) ;
wrapper . HasIncompleteInterfaceImplementation = true ;
}
else if ( mce . GetMethod ( ) = = null | | mce . RealName ! = ifmethod . RealName )
{
2005-09-01 11:34:53 +04:00
MethodBuilder mb = typeBuilder . DefineMethod ( mangledName , MethodAttributes . HideBySig | MethodAttributes . NewSlot | MethodAttributes . Private | MethodAttributes . Virtual | MethodAttributes . Final , ifmethod . ReturnTypeForDefineMethod , ifmethod . GetParametersForDefineMethod ( ) ) ;
2005-06-01 13:49:30 +04:00
AttributeHelper . HideFromJava ( mb ) ;
ILGenerator ilGenerator = mb . GetILGenerator ( ) ;
ilGenerator . Emit ( OpCodes . Ldarg_0 ) ;
int argc = mce . GetParameters ( ) . Length ;
for ( int n = 0 ; n < argc ; n + + )
{
ilGenerator . Emit ( OpCodes . Ldarg_S , ( byte ) ( n + 1 ) ) ;
}
mce . EmitCallvirt ( ilGenerator ) ;
ilGenerator . Emit ( OpCodes . Ret ) ;
typeBuilder . DefineMethodOverride ( mb , ( MethodInfo ) ifmethod . GetMethod ( ) ) ;
}
else if ( mce . DeclaringType . TypeAsTBD . Assembly ! = typeBuilder . Assembly )
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
// NOTE methods inherited from base classes in a different assembly do *not* automatically implement
// interface methods, so we have to generate a stub here that doesn't do anything but call the base
// implementation
2005-09-01 11:34:53 +04:00
MethodBuilder mb = typeBuilder . DefineMethod ( mangledName , MethodAttributes . HideBySig | MethodAttributes . NewSlot | MethodAttributes . Private | MethodAttributes . Virtual | MethodAttributes . Final , ifmethod . ReturnTypeForDefineMethod , ifmethod . GetParametersForDefineMethod ( ) ) ;
2005-06-01 13:49:30 +04:00
typeBuilder . DefineMethodOverride ( mb , ( MethodInfo ) ifmethod . GetMethod ( ) ) ;
AttributeHelper . HideFromJava ( mb ) ;
ILGenerator ilGenerator = mb . GetILGenerator ( ) ;
ilGenerator . Emit ( OpCodes . Ldarg_0 ) ;
int argc = mce . GetParameters ( ) . Length ;
for ( int n = 0 ; n < argc ; n + + )
{
ilGenerator . Emit ( OpCodes . Ldarg_S , ( byte ) ( n + 1 ) ) ;
}
mce . EmitCallvirt ( ilGenerator ) ;
ilGenerator . Emit ( OpCodes . Ret ) ;
2002-12-18 19:00:25 +03:00
}
}
2005-06-01 13:49:30 +04:00
else
2002-12-29 19:27:00 +03:00
{
2005-06-01 13:49:30 +04:00
if ( ! wrapper . IsAbstract )
2002-12-29 19:27:00 +03:00
{
2005-06-01 13:49:30 +04:00
// the type doesn't implement the interface method and isn't abstract either. The JVM allows this, but the CLR doesn't,
// so we have to create a stub method that throws an AbstractMethodError
2005-09-01 11:34:53 +04:00
MethodBuilder mb = typeBuilder . DefineMethod ( mangledName , MethodAttributes . HideBySig | MethodAttributes . NewSlot | MethodAttributes . Private | MethodAttributes . Virtual | MethodAttributes . Final , ifmethod . ReturnTypeForDefineMethod , ifmethod . GetParametersForDefineMethod ( ) ) ;
2005-06-01 13:49:30 +04:00
AttributeHelper . HideFromJava ( mb ) ;
EmitHelper . Throw ( mb . GetILGenerator ( ) , "java.lang.AbstractMethodError" , wrapper . Name + "." + ifmethod . Name + ifmethod . Signature ) ;
typeBuilder . DefineMethodOverride ( mb , ( MethodInfo ) ifmethod . GetMethod ( ) ) ;
wrapper . HasIncompleteInterfaceImplementation = true ;
2002-12-29 19:27:00 +03:00
}
}
2002-12-18 19:00:25 +03:00
}
2005-06-01 13:49:30 +04:00
internal void ImplementInterfaceMethodStubs ( TypeBuilder typeBuilder , DynamicTypeWrapper wrapper , Hashtable doneSet )
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
Debug . Assert ( this . IsInterface ) ;
// make sure we don't do the same method twice
if ( doneSet . ContainsKey ( this ) )
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
return ;
2002-12-18 19:00:25 +03:00
}
2005-06-01 13:49:30 +04:00
doneSet . Add ( this , this ) ;
foreach ( MethodWrapper method in GetMethods ( ) )
{
if ( ! method . IsStatic )
{
ImplementInterfaceMethodStubImpl ( method , typeBuilder , wrapper ) ;
}
}
TypeWrapper [ ] interfaces = Interfaces ;
for ( int i = 0 ; i < interfaces . Length ; i + + )
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
interfaces [ i ] . ImplementInterfaceMethodStubs ( typeBuilder , wrapper , doneSet ) ;
2002-12-18 19:00:25 +03:00
}
}
2005-12-07 12:06:32 +03:00
#endif
2002-12-18 19:00:25 +03:00
2005-06-01 13:49:30 +04:00
[Conditional("DEBUG")]
internal static void AssertFinished ( Type type )
2003-02-22 15:28:12 +03:00
{
2005-06-01 13:49:30 +04:00
if ( type ! = null )
2003-02-22 15:28:12 +03:00
{
2005-06-01 13:49:30 +04:00
while ( type . IsArray )
{
type = type . GetElementType ( ) ;
}
Debug . Assert ( ! ( type is TypeBuilder ) ) ;
2003-02-22 15:28:12 +03:00
}
}
2003-12-20 01:19:18 +03:00
2005-06-01 13:49:30 +04:00
internal void RunClassInit ( )
2005-02-02 18:11:26 +03:00
{
2005-06-01 13:49:30 +04:00
System . Runtime . CompilerServices . RuntimeHelpers . RunClassConstructor ( TypeAsTBD . TypeHandle ) ;
2005-02-02 18:11:26 +03:00
}
2005-06-01 13:49:30 +04:00
2005-12-07 12:06:32 +03:00
#if ! COMPACT_FRAMEWORK
2005-12-19 18:12:49 +03:00
internal void EmitUnbox ( CountingILGenerator ilgen )
2005-02-02 18:11:26 +03:00
{
2005-06-01 13:49:30 +04:00
Debug . Assert ( this . IsNonPrimitiveValueType ) ;
2005-12-19 18:12:49 +03:00
ilgen . LazyEmitUnboxSpecial ( this . TypeAsTBD ) ;
2005-02-02 18:11:26 +03:00
}
2005-06-01 13:49:30 +04:00
2005-12-19 18:12:49 +03:00
internal void EmitBox ( CountingILGenerator ilgen )
2005-02-02 18:11:26 +03:00
{
2005-06-01 13:49:30 +04:00
Debug . Assert ( this . IsNonPrimitiveValueType ) ;
2005-12-19 18:12:49 +03:00
ilgen . LazyEmitBox ( this . TypeAsTBD ) ;
2005-02-02 18:11:26 +03:00
}
2005-06-01 13:49:30 +04:00
internal void EmitConvSignatureTypeToStackType ( ILGenerator ilgen )
2003-12-20 01:19:18 +03:00
{
2005-06-01 13:49:30 +04:00
if ( IsUnloadable )
2003-12-20 01:19:18 +03:00
{
}
2005-06-01 13:49:30 +04:00
else if ( this = = PrimitiveTypeWrapper . BYTE )
2004-03-08 18:18:47 +03:00
{
2005-06-01 13:49:30 +04:00
ilgen . Emit ( OpCodes . Conv_I1 ) ;
2004-03-08 18:18:47 +03:00
}
else if ( IsNonPrimitiveValueType )
{
2005-06-01 13:49:30 +04:00
EmitBox ( ilgen ) ;
}
else if ( IsGhost )
{
LocalBuilder local = ilgen . DeclareLocal ( TypeAsSignatureType ) ;
ilgen . Emit ( OpCodes . Stloc , local ) ;
ilgen . Emit ( OpCodes . Ldloca , local ) ;
ilgen . Emit ( OpCodes . Ldfld , GhostRefField ) ;
2004-03-08 18:18:47 +03:00
}
2003-12-20 01:19:18 +03:00
}
2005-06-01 13:49:30 +04:00
// NOTE sourceType is optional and only used for interfaces,
// it is *not* used to automatically downcast
internal void EmitConvStackTypeToSignatureType ( ILGenerator ilgen , TypeWrapper sourceType )
2004-01-11 16:14:42 +03:00
{
2005-06-01 13:49:30 +04:00
if ( ! IsUnloadable )
2004-01-11 16:14:42 +03:00
{
2005-06-01 13:49:30 +04:00
if ( IsGhost )
{
LocalBuilder local1 = ilgen . DeclareLocal ( TypeAsLocalOrStackType ) ;
ilgen . Emit ( OpCodes . Stloc , local1 ) ;
LocalBuilder local2 = ilgen . DeclareLocal ( TypeAsSignatureType ) ;
ilgen . Emit ( OpCodes . Ldloca , local2 ) ;
ilgen . Emit ( OpCodes . Ldloc , local1 ) ;
ilgen . Emit ( OpCodes . Stfld , GhostRefField ) ;
ilgen . Emit ( OpCodes . Ldloca , local2 ) ;
ilgen . Emit ( OpCodes . Ldobj , TypeAsSignatureType ) ;
}
// because of the way interface merging works, any reference is valid
// for any interface reference
else if ( IsInterfaceOrInterfaceArray & & ( sourceType = = null | | sourceType . IsUnloadable | | ! sourceType . IsAssignableTo ( this ) ) )
{
EmitHelper . EmitAssertType ( ilgen , TypeAsTBD ) ;
Profiler . Count ( "InterfaceDownCast" ) ;
}
else if ( IsNonPrimitiveValueType )
{
EmitUnbox ( ilgen ) ;
}
2005-08-05 16:18:35 +04:00
else if ( sourceType ! = null & & sourceType . IsUnloadable )
{
ilgen . Emit ( OpCodes . Castclass , TypeAsSignatureType ) ;
}
2004-01-11 16:14:42 +03:00
}
}
2005-06-01 13:49:30 +04:00
internal virtual void EmitCheckcast ( TypeWrapper context , ILGenerator ilgen )
2004-01-11 16:14:42 +03:00
{
2005-06-01 13:49:30 +04:00
if ( IsGhost )
{
ilgen . Emit ( OpCodes . Dup ) ;
// TODO make sure we get the right "Cast" method and cache it
// NOTE for dynamic ghosts we don't end up here because DynamicTypeWrapper overrides this method,
// so we're safe to call GetMethod on TypeAsTBD (because it has to be a compiled type, if we're here)
ilgen . Emit ( OpCodes . Call , TypeAsTBD . GetMethod ( "Cast" ) ) ;
ilgen . Emit ( OpCodes . Pop ) ;
}
else if ( IsGhostArray )
{
ilgen . Emit ( OpCodes . Dup ) ;
// TODO make sure we get the right "CastArray" method and cache it
// NOTE for dynamic ghosts we don't end up here because DynamicTypeWrapper overrides this method,
// so we're safe to call GetMethod on TypeAsTBD (because it has to be a compiled type, if we're here)
TypeWrapper tw = this ;
int rank = 0 ;
while ( tw . IsArray )
{
rank + + ;
tw = tw . ElementTypeWrapper ;
}
ilgen . Emit ( OpCodes . Ldc_I4 , rank ) ;
ilgen . Emit ( OpCodes . Call , tw . TypeAsTBD . GetMethod ( "CastArray" ) ) ;
}
else
{
EmitHelper . Castclass ( ilgen , TypeAsTBD ) ;
}
2004-01-11 16:14:42 +03:00
}
2005-06-01 13:49:30 +04:00
internal virtual void EmitInstanceOf ( TypeWrapper context , ILGenerator ilgen )
2004-01-11 16:14:42 +03:00
{
2005-06-01 13:49:30 +04:00
if ( IsGhost )
{
// TODO make sure we get the right "IsInstance" method and cache it
// NOTE for dynamic ghosts we don't end up here because DynamicTypeWrapper overrides this method,
// so we're safe to call GetMethod on TypeAsTBD (because it has to be a compiled type, if we're here)
ilgen . Emit ( OpCodes . Call , TypeAsTBD . GetMethod ( "IsInstance" ) ) ;
}
else if ( IsGhostArray )
{
// TODO make sure we get the right "IsInstanceArray" method and cache it
// NOTE for dynamic ghosts we don't end up here because DynamicTypeWrapper overrides this method,
// so we're safe to call GetMethod on TypeAsTBD (because it has to be a compiled type, if we're here)
ilgen . Emit ( OpCodes . Call , TypeAsTBD . GetMethod ( "IsInstanceArray" ) ) ;
}
else
{
ilgen . Emit ( OpCodes . Isinst , TypeAsTBD ) ;
ilgen . Emit ( OpCodes . Ldnull ) ;
ilgen . Emit ( OpCodes . Cgt_Un ) ;
}
2004-01-11 16:14:42 +03:00
}
2005-12-07 12:06:32 +03:00
#endif
2005-06-01 13:49:30 +04:00
internal static string GetSigNameFromType ( Type type )
2004-01-11 16:14:42 +03:00
{
2005-06-01 13:49:30 +04:00
TypeWrapper wrapper = ClassLoaderWrapper . GetWrapperFromTypeFast ( type ) ;
2004-01-11 16:14:42 +03:00
2005-06-01 13:49:30 +04:00
if ( wrapper ! = null )
{
return wrapper . SigName ;
}
2004-01-11 16:14:42 +03:00
2005-06-01 13:49:30 +04:00
if ( type . IsArray )
{
System . Text . StringBuilder sb = new System . Text . StringBuilder ( ) ;
while ( type . IsArray )
{
sb . Append ( '[' ) ;
type = type . GetElementType ( ) ;
}
return sb . Append ( GetSigNameFromType ( type ) ) . ToString ( ) ;
}
2004-01-11 16:14:42 +03:00
2005-06-01 13:49:30 +04:00
string s = TypeWrapper . GetNameFromType ( type ) ;
if ( s [ 0 ] ! = '[' )
2004-01-11 16:14:42 +03:00
{
2005-06-01 13:49:30 +04:00
s = "L" + s + ";" ;
2004-01-11 16:14:42 +03:00
}
2005-06-01 13:49:30 +04:00
return s ;
2004-01-11 16:14:42 +03:00
}
2006-01-23 13:18:44 +03:00
// NOTE returns null for primitive types and types that are not visible from Java (e.g. open generic types)
2005-06-01 13:49:30 +04:00
internal static string GetNameFromType ( Type type )
2004-01-11 16:14:42 +03:00
{
2005-06-01 13:49:30 +04:00
TypeWrapper . AssertFinished ( type ) ;
2004-01-11 16:14:42 +03:00
2005-06-01 13:49:30 +04:00
if ( type . IsArray )
{
return GetSigNameFromType ( type ) ;
}
2004-01-11 16:14:42 +03:00
2005-06-01 13:49:30 +04:00
// first we check if a wrapper exists, because if it does we must use the name from the wrapper to
// make sure that remapped types return the proper name
TypeWrapper wrapper = ClassLoaderWrapper . GetWrapperFromTypeFast ( type ) ;
if ( wrapper ! = null )
{
return wrapper . Name ;
}
2004-01-11 16:14:42 +03:00
2005-12-07 12:06:32 +03:00
if ( AttributeHelper . IsJavaModule ( type . Module ) )
2005-06-01 13:49:30 +04:00
{
return CompiledTypeWrapper . GetName ( type ) ;
}
else
{
return DotNetTypeWrapper . GetName ( type ) ;
}
2004-01-11 16:14:42 +03:00
}
2005-06-01 13:49:30 +04:00
// NOTE don't call this method, call MethodWrapper.Link instead
internal virtual MethodBase LinkMethod ( MethodWrapper mw )
2004-01-11 16:14:42 +03:00
{
2005-06-01 13:49:30 +04:00
return mw . GetMethod ( ) ;
2004-01-11 16:14:42 +03:00
}
2005-06-01 13:49:30 +04:00
// NOTE don't call this method, call FieldWrapper.Link instead
internal virtual FieldInfo LinkField ( FieldWrapper fw )
2004-01-11 16:14:42 +03:00
{
2005-06-01 13:49:30 +04:00
return fw . GetField ( ) ;
2004-01-11 16:14:42 +03:00
}
2005-08-24 12:14:23 +04:00
2005-12-07 12:06:32 +03:00
#if ! COMPACT_FRAMEWORK
2005-08-24 12:14:23 +04:00
internal virtual void EmitRunClassConstructor ( ILGenerator ilgen )
{
}
2005-12-07 12:06:32 +03:00
#endif
2005-10-01 15:16:11 +04:00
internal abstract string GetGenericSignature ( ) ;
internal abstract string GetGenericMethodSignature ( MethodWrapper mw ) ;
internal abstract string GetGenericFieldSignature ( FieldWrapper fw ) ;
internal abstract string [ ] GetEnclosingMethod ( ) ;
2005-11-01 17:01:42 +03:00
internal virtual object [ ] GetDeclaredAnnotations ( )
{
return null ;
}
2006-04-19 19:49:54 +04:00
internal virtual object [ ] GetMethodAnnotations ( MethodWrapper mw )
{
return null ;
}
internal virtual object [ ] [ ] GetParameterAnnotations ( MethodWrapper mw )
{
return null ;
}
internal virtual object [ ] GetFieldAnnotations ( FieldWrapper fw )
{
return null ;
}
2006-04-10 13:09:09 +04:00
#if ! STATIC_COMPILER
2005-11-01 17:01:42 +03:00
internal virtual object GetAnnotationDefault ( MethodWrapper mw )
{
MethodBase mb = mw . GetMethod ( ) ;
if ( mb ! = null )
{
object [ ] attr = mb . GetCustomAttributes ( typeof ( AnnotationDefaultAttribute ) , false ) ;
if ( attr . Length = = 1 )
{
return JVM . Library . newAnnotationElementValue ( mw . DeclaringType . GetClassLoader ( ) . GetJavaClassLoader ( ) , mw . ReturnType . ClassObject , ( ( AnnotationDefaultAttribute ) attr [ 0 ] ) . Value ) ;
}
}
return null ;
}
2006-04-10 13:09:09 +04:00
#endif
2005-11-01 17:01:42 +03:00
2005-12-07 12:06:32 +03:00
#if ! COMPACT_FRAMEWORK
2005-11-01 17:01:42 +03:00
internal virtual Annotation Annotation
{
get
{
return null ;
}
}
2005-12-07 12:06:32 +03:00
#endif
2004-01-11 16:14:42 +03:00
}
2004-08-17 13:05:21 +04:00
2005-06-01 13:49:30 +04:00
class UnloadableTypeWrapper : TypeWrapper
2004-08-17 13:05:21 +04:00
{
2006-04-10 13:09:09 +04:00
#if STATIC_COMPILER
2005-06-01 13:49:30 +04:00
private static Hashtable warningHashtable ;
2006-04-10 13:09:09 +04:00
#endif
2002-12-18 19:00:25 +03:00
2005-06-01 13:49:30 +04:00
internal UnloadableTypeWrapper ( string name )
2006-03-23 14:57:41 +03:00
: base ( TypeWrapper . UnloadableModifiersHack , name , null )
2005-06-01 13:49:30 +04:00
{
2006-04-10 13:09:09 +04:00
#if STATIC_COMPILER
if ( name ! = "<verifier>" )
2005-06-01 13:49:30 +04:00
{
if ( warningHashtable = = null )
{
warningHashtable = new Hashtable ( ) ;
}
if ( name . StartsWith ( "[" ) )
{
int skip = 1 ;
while ( name [ skip + + ] = = '[' ) ;
name = name . Substring ( skip , name . Length - skip - 1 ) ;
}
if ( ! warningHashtable . ContainsKey ( name ) )
{
warningHashtable . Add ( name , name ) ;
Console . Error . WriteLine ( "Warning: class \"{0}\" not found" , name ) ;
}
}
2006-04-10 13:09:09 +04:00
#endif
2005-06-01 13:49:30 +04:00
}
2005-02-23 15:56:15 +03:00
2006-03-23 14:57:41 +03:00
internal override ClassLoaderWrapper GetClassLoader ( )
{
return null ;
}
2005-06-01 13:49:30 +04:00
internal override TypeWrapper EnsureLoadable ( ClassLoaderWrapper loader )
2005-02-23 15:56:15 +03:00
{
2005-08-25 11:46:57 +04:00
TypeWrapper tw = loader . LoadClassByDottedNameFast ( this . Name ) ;
2005-06-01 13:49:30 +04:00
if ( tw = = null )
2005-02-23 15:56:15 +03:00
{
2005-06-01 13:49:30 +04:00
throw new NoClassDefFoundError ( this . Name ) ;
2005-02-23 15:56:15 +03:00
}
2005-06-01 13:49:30 +04:00
return tw ;
2005-02-23 15:56:15 +03:00
}
2005-06-01 13:49:30 +04:00
internal override Assembly Assembly
2005-02-23 15:56:15 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
return null ;
}
2005-02-23 15:56:15 +03:00
}
2005-06-01 13:49:30 +04:00
internal override string SigName
2005-02-23 15:56:15 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
string name = Name ;
if ( name . StartsWith ( "[" ) )
{
return name ;
}
return "L" + name + ";" ;
}
2005-02-23 15:56:15 +03:00
}
2005-06-01 13:49:30 +04:00
protected override void LazyPublishMembers ( )
2005-02-23 15:56:15 +03:00
{
2005-06-01 13:49:30 +04:00
throw new InvalidOperationException ( "LazyPublishMembers called on UnloadableTypeWrapper: " + Name ) ;
2005-02-23 15:56:15 +03:00
}
2003-01-06 16:56:37 +03:00
2005-06-01 13:49:30 +04:00
internal override Type TypeAsTBD
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
get
{
throw new InvalidOperationException ( "get_Type called on UnloadableTypeWrapper: " + Name ) ;
}
}
2004-08-17 13:05:21 +04:00
2005-06-01 13:49:30 +04:00
internal override TypeWrapper [ ] Interfaces
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
get
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
throw new InvalidOperationException ( "get_Interfaces called on UnloadableTypeWrapper: " + Name ) ;
2004-08-17 13:05:21 +04:00
}
}
2005-06-01 13:49:30 +04:00
internal override TypeWrapper [ ] InnerClasses
{
get
{
throw new InvalidOperationException ( "get_InnerClasses called on UnloadableTypeWrapper: " + Name ) ;
}
}
2003-01-06 16:56:37 +03:00
2005-06-01 13:49:30 +04:00
internal override TypeWrapper DeclaringTypeWrapper
2003-01-06 16:56:37 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
throw new InvalidOperationException ( "get_DeclaringTypeWrapper called on UnloadableTypeWrapper: " + Name ) ;
}
}
2003-01-06 16:56:37 +03:00
2005-08-05 12:40:54 +04:00
internal override void Finish ( )
2003-01-06 16:56:37 +03:00
{
2005-06-01 13:49:30 +04:00
throw new InvalidOperationException ( "Finish called on UnloadableTypeWrapper: " + Name ) ;
2003-01-06 16:56:37 +03:00
}
2005-12-07 12:06:32 +03:00
#if ! COMPACT_FRAMEWORK
2005-06-01 13:49:30 +04:00
internal override void EmitCheckcast ( TypeWrapper context , ILGenerator ilgen )
2003-02-18 12:30:34 +03:00
{
2005-06-01 13:49:30 +04:00
ilgen . Emit ( OpCodes . Ldtoken , context . TypeAsTBD ) ;
ilgen . Emit ( OpCodes . Ldstr , Name ) ;
2006-04-11 16:05:24 +04:00
ilgen . Emit ( OpCodes . Call , ByteCodeHelperMethods . DynamicCast ) ;
2003-02-18 12:30:34 +03:00
}
2005-06-01 13:49:30 +04:00
internal override void EmitInstanceOf ( TypeWrapper context , ILGenerator ilgen )
2003-02-18 12:30:34 +03:00
{
2005-06-01 13:49:30 +04:00
ilgen . Emit ( OpCodes . Ldtoken , context . TypeAsTBD ) ;
ilgen . Emit ( OpCodes . Ldstr , Name ) ;
2006-04-11 16:05:24 +04:00
ilgen . Emit ( OpCodes . Call , ByteCodeHelperMethods . DynamicInstanceOf ) ;
2003-02-18 12:30:34 +03:00
}
2005-12-07 12:06:32 +03:00
#endif
2005-10-01 15:16:11 +04:00
internal override string GetGenericSignature ( )
{
throw new InvalidOperationException ( "GetGenericSignature called on UnloadableTypeWrapper: " + Name ) ;
}
internal override string GetGenericMethodSignature ( MethodWrapper mw )
{
throw new InvalidOperationException ( "GetGenericMethodSignature called on UnloadableTypeWrapper: " + Name ) ;
}
internal override string GetGenericFieldSignature ( FieldWrapper fw )
{
throw new InvalidOperationException ( "GetGenericFieldSignature called on UnloadableTypeWrapper: " + Name ) ;
}
internal override string [ ] GetEnclosingMethod ( )
{
throw new InvalidOperationException ( "GetEnclosingMethod called on UnloadableTypeWrapper: " + Name ) ;
}
2003-02-18 12:30:34 +03:00
}
2005-06-01 13:49:30 +04:00
class PrimitiveTypeWrapper : TypeWrapper
2003-01-06 16:56:37 +03:00
{
2005-06-01 13:49:30 +04:00
internal static readonly PrimitiveTypeWrapper BYTE = new PrimitiveTypeWrapper ( typeof ( byte ) , "B" ) ;
internal static readonly PrimitiveTypeWrapper CHAR = new PrimitiveTypeWrapper ( typeof ( char ) , "C" ) ;
internal static readonly PrimitiveTypeWrapper DOUBLE = new PrimitiveTypeWrapper ( typeof ( double ) , "D" ) ;
internal static readonly PrimitiveTypeWrapper FLOAT = new PrimitiveTypeWrapper ( typeof ( float ) , "F" ) ;
internal static readonly PrimitiveTypeWrapper INT = new PrimitiveTypeWrapper ( typeof ( int ) , "I" ) ;
internal static readonly PrimitiveTypeWrapper LONG = new PrimitiveTypeWrapper ( typeof ( long ) , "J" ) ;
internal static readonly PrimitiveTypeWrapper SHORT = new PrimitiveTypeWrapper ( typeof ( short ) , "S" ) ;
internal static readonly PrimitiveTypeWrapper BOOLEAN = new PrimitiveTypeWrapper ( typeof ( bool ) , "Z" ) ;
internal static readonly PrimitiveTypeWrapper VOID = new PrimitiveTypeWrapper ( typeof ( void ) , "V" ) ;
2004-01-11 16:14:42 +03:00
2005-06-01 13:49:30 +04:00
private readonly Type type ;
private readonly string sigName ;
2004-01-11 16:14:42 +03:00
2005-06-01 13:49:30 +04:00
private PrimitiveTypeWrapper ( Type type , string sigName )
2006-03-23 14:57:41 +03:00
: base ( Modifiers . Public | Modifiers . Abstract | Modifiers . Final , null , null )
2005-06-01 13:49:30 +04:00
{
this . type = type ;
this . sigName = sigName ;
}
2003-01-06 16:56:37 +03:00
2005-06-01 13:49:30 +04:00
internal override Assembly Assembly
{
get
{
return null ;
}
}
2003-08-21 14:06:34 +04:00
2005-06-01 13:49:30 +04:00
internal override string SigName
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
get
{
return sigName ;
}
2004-08-17 13:05:21 +04:00
}
2005-06-01 13:49:30 +04:00
internal override ClassLoaderWrapper GetClassLoader ( )
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
return ClassLoaderWrapper . GetBootstrapClassLoader ( ) ;
2003-08-21 14:06:34 +04:00
}
2002-12-18 19:00:25 +03:00
2005-06-01 13:49:30 +04:00
internal override Type TypeAsTBD
{
get
{
return type ;
}
}
2003-04-14 13:41:58 +04:00
2005-06-01 13:49:30 +04:00
internal override TypeWrapper [ ] Interfaces
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
return TypeWrapper . EmptyArray ;
}
2002-12-18 19:00:25 +03:00
}
2005-06-01 13:49:30 +04:00
internal override TypeWrapper [ ] InnerClasses
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
return TypeWrapper . EmptyArray ;
}
2002-12-18 19:00:25 +03:00
}
2005-06-01 13:49:30 +04:00
internal override TypeWrapper DeclaringTypeWrapper
2003-02-18 12:30:34 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
return null ;
}
2003-02-18 12:30:34 +03:00
}
2005-08-05 12:40:54 +04:00
internal override void Finish ( )
2003-02-18 12:30:34 +03:00
{
}
2005-06-01 13:49:30 +04:00
public override string ToString ( )
{
return "PrimitiveTypeWrapper[" + sigName + "]" ;
}
2005-10-01 15:16:11 +04:00
internal override string GetGenericSignature ( )
{
return null ;
}
internal override string GetGenericMethodSignature ( MethodWrapper mw )
{
return null ;
}
internal override string GetGenericFieldSignature ( FieldWrapper fw )
{
return null ;
}
internal override string [ ] GetEnclosingMethod ( )
{
return null ;
}
2002-12-18 19:00:25 +03:00
}
2005-02-02 18:11:26 +03:00
2005-12-07 12:06:32 +03:00
#if ! COMPACT_FRAMEWORK
2005-06-01 13:49:30 +04:00
class BakedTypeCleanupHack
2005-02-02 18:11:26 +03:00
{
2005-06-01 13:49:30 +04:00
private static readonly FieldInfo m_methodBuilder = typeof ( ConstructorBuilder ) . GetField ( "m_methodBuilder" , BindingFlags . Instance | BindingFlags . NonPublic ) ;
private static readonly FieldInfo [ ] methodBuilderFields = GetFieldList ( typeof ( MethodBuilder ) , new string [ ]
2005-01-03 11:26:21 +03:00
{
"m_ilGenerator" ,
"m_ubBody" ,
"m_RVAFixups" ,
"mm_mdMethodFixups" ,
"m_localSignature" ,
"m_localSymInfo" ,
"m_exceptions" ,
"m_parameterTypes" ,
"m_retParam" ,
"m_returnType" ,
"m_signature"
} ) ;
2005-06-01 13:49:30 +04:00
private static readonly FieldInfo [ ] fieldBuilderFields = GetFieldList ( typeof ( FieldBuilder ) , new string [ ]
2005-01-03 11:26:21 +03:00
{
"m_data" ,
"m_fieldType" ,
2005-06-01 13:49:30 +04:00
} ) ;
2005-01-03 11:26:21 +03:00
2005-06-01 13:49:30 +04:00
private static bool IsSupportedVersion
2005-01-05 15:11:50 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
return Environment . Version . Major = = 1 & & Environment . Version . Minor = = 1 & & Environment . Version . Build = = 4322 ;
}
2005-01-05 15:11:50 +03:00
}
2005-06-01 13:49:30 +04:00
private static FieldInfo [ ] GetFieldList ( Type type , string [ ] list )
2005-01-03 11:26:21 +03:00
{
2005-08-03 16:59:16 +04:00
if ( JVM . SafeGetEnvironmentVariable ( "IKVM_DISABLE_TYPEBUILDER_HACK" ) ! = null | | ! IsSupportedVersion )
2005-01-03 11:26:21 +03:00
{
return null ;
}
2005-06-01 13:49:30 +04:00
if ( ! SecurityManager . IsGranted ( new SecurityPermission ( SecurityPermissionFlag . Assertion ) ) | |
! SecurityManager . IsGranted ( new ReflectionPermission ( ReflectionPermissionFlag . MemberAccess ) ) )
{
return null ;
}
FieldInfo [ ] fields = new FieldInfo [ list . Length ] ;
for ( int i = 0 ; i < list . Length ; i + + )
{
fields [ i ] = type . GetField ( list [ i ] , BindingFlags . Instance | BindingFlags . NonPublic ) ;
if ( fields [ i ] = = null )
{
return null ;
}
}
return fields ;
2005-01-03 11:26:21 +03:00
}
2005-06-01 13:49:30 +04:00
internal static void Process ( DynamicTypeWrapper wrapper )
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
if ( m_methodBuilder ! = null & & methodBuilderFields ! = null & & fieldBuilderFields ! = null )
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
foreach ( MethodWrapper mw in wrapper . GetMethods ( ) )
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
MethodBuilder mb = mw . GetMethod ( ) as MethodBuilder ;
if ( mb = = null )
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
ConstructorBuilder cb = mw . GetMethod ( ) as ConstructorBuilder ;
if ( cb ! = null )
{
new ReflectionPermission ( ReflectionPermissionFlag . MemberAccess ) . Assert ( ) ;
mb = ( MethodBuilder ) m_methodBuilder . GetValue ( cb ) ;
CodeAccessPermission . RevertAssert ( ) ;
}
2005-01-03 11:26:21 +03:00
}
2005-06-01 13:49:30 +04:00
if ( mb ! = null )
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
new ReflectionPermission ( ReflectionPermissionFlag . MemberAccess ) . Assert ( ) ;
foreach ( FieldInfo fi in methodBuilderFields )
{
fi . SetValue ( mb , null ) ;
}
CodeAccessPermission . RevertAssert ( ) ;
2005-01-03 11:26:21 +03:00
}
}
2005-06-01 13:49:30 +04:00
foreach ( FieldWrapper fw in wrapper . GetFields ( ) )
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
FieldBuilder fb = fw . GetField ( ) as FieldBuilder ;
if ( fb ! = null )
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
new ReflectionPermission ( ReflectionPermissionFlag . MemberAccess ) . Assert ( ) ;
foreach ( FieldInfo fi in fieldBuilderFields )
{
fi . SetValue ( fb , null ) ;
}
CodeAccessPermission . RevertAssert ( ) ;
2005-01-03 11:26:21 +03:00
}
}
}
}
}
2002-12-18 19:00:25 +03:00
2005-06-01 13:49:30 +04:00
class DynamicTypeWrapper : TypeWrapper
2004-08-17 13:05:21 +04:00
{
2006-03-23 14:57:41 +03:00
protected readonly DynamicClassLoader classLoader ;
2005-06-01 13:49:30 +04:00
private volatile DynamicImpl impl ;
private TypeWrapper [ ] interfaces ;
2004-08-17 13:05:21 +04:00
2005-06-01 13:49:30 +04:00
private static TypeWrapper LoadTypeWrapper ( ClassLoaderWrapper classLoader , string name )
2003-01-06 16:56:37 +03:00
{
2005-06-01 13:49:30 +04:00
TypeWrapper tw = classLoader . LoadClassByDottedNameFast ( name ) ;
if ( tw = = null )
2003-06-10 17:28:47 +04:00
{
2005-06-01 13:49:30 +04:00
throw new NoClassDefFoundError ( name ) ;
2003-06-10 17:28:47 +04:00
}
2005-06-01 13:49:30 +04:00
return tw ;
}
2006-03-23 14:57:41 +03:00
internal DynamicTypeWrapper ( ClassFile f , DynamicClassLoader classLoader )
: base ( f . Modifiers , f . Name , f . IsInterface ? null : LoadTypeWrapper ( classLoader , f . SuperClass ) )
2005-06-01 13:49:30 +04:00
{
Profiler . Count ( "DynamicTypeWrapper" ) ;
2006-03-23 14:57:41 +03:00
this . classLoader = classLoader ;
2006-04-05 12:18:58 +04:00
this . IsInternal = f . IsInternal ;
2005-06-01 13:49:30 +04:00
if ( BaseTypeWrapper ! = null )
2004-10-04 23:30:53 +04:00
{
2005-06-01 13:49:30 +04:00
if ( ! BaseTypeWrapper . IsAccessibleFrom ( this ) )
{
throw new IllegalAccessError ( "Class " + f . Name + " cannot access its superclass " + BaseTypeWrapper . Name ) ;
}
if ( BaseTypeWrapper . IsFinal )
{
2005-07-27 19:57:55 +04:00
throw new VerifyError ( "Class " + f . Name + " extends final class " + BaseTypeWrapper . Name ) ;
2005-06-01 13:49:30 +04:00
}
if ( BaseTypeWrapper . IsInterface )
{
throw new IncompatibleClassChangeError ( "Class " + f . Name + " has interface " + BaseTypeWrapper . Name + " as superclass" ) ;
}
if ( ! f . IsFinal )
{
if ( BaseTypeWrapper . TypeAsTBD = = typeof ( ValueType ) | | BaseTypeWrapper . TypeAsTBD = = typeof ( Enum ) )
{
throw new VerifyError ( "Value types must be final" ) ;
}
if ( BaseTypeWrapper . TypeAsTBD = = typeof ( MulticastDelegate ) )
{
throw new VerifyError ( "Delegates must be final" ) ;
}
}
if ( BaseTypeWrapper . TypeAsTBD = = typeof ( Delegate ) )
{
throw new VerifyError ( BaseTypeWrapper . Name + " cannot be used as a base class" ) ;
}
// NOTE defining value types, enums and delegates is not supported in IKVM v1
2004-10-04 23:30:53 +04:00
if ( BaseTypeWrapper . TypeAsTBD = = typeof ( ValueType ) | | BaseTypeWrapper . TypeAsTBD = = typeof ( Enum ) )
{
2005-06-01 13:49:30 +04:00
throw new VerifyError ( "Defining value types in Java is not implemented in IKVM v1" ) ;
2004-10-04 23:30:53 +04:00
}
if ( BaseTypeWrapper . TypeAsTBD = = typeof ( MulticastDelegate ) )
{
2005-06-01 13:49:30 +04:00
throw new VerifyError ( "Defining delegates in Java is not implemented in IKVM v1" ) ;
2004-10-04 23:30:53 +04:00
}
}
2005-06-01 13:49:30 +04:00
ClassFile . ConstantPoolItemClass [ ] interfaces = f . Interfaces ;
this . interfaces = new TypeWrapper [ interfaces . Length ] ;
for ( int i = 0 ; i < interfaces . Length ; i + + )
2004-10-04 23:30:53 +04:00
{
2005-06-01 13:49:30 +04:00
TypeWrapper iface = LoadTypeWrapper ( classLoader , interfaces [ i ] . Name ) ;
if ( ! iface . IsAccessibleFrom ( this ) )
{
throw new IllegalAccessError ( "Class " + f . Name + " cannot access its superinterface " + iface . Name ) ;
}
if ( ! iface . IsInterface )
{
throw new IncompatibleClassChangeError ( "Implementing class" ) ;
}
this . interfaces [ i ] = iface ;
2004-10-04 23:30:53 +04:00
}
2005-06-01 13:49:30 +04:00
impl = new JavaTypeImpl ( f , this ) ;
2003-01-06 16:56:37 +03:00
}
2004-08-17 13:05:21 +04:00
2006-03-23 14:57:41 +03:00
internal override ClassLoaderWrapper GetClassLoader ( )
{
return classLoader ;
}
2005-06-01 13:49:30 +04:00
internal override Assembly Assembly
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
get
{
2006-03-23 14:57:41 +03:00
return classLoader . ModuleBuilder . Assembly ;
2005-06-01 13:49:30 +04:00
}
2004-08-17 13:05:21 +04:00
}
2005-06-01 13:49:30 +04:00
internal override Modifiers ReflectiveModifiers
2003-05-30 16:08:59 +04:00
{
2005-06-01 13:49:30 +04:00
get
{
return impl . ReflectiveModifiers ;
}
2003-05-30 16:08:59 +04:00
}
2002-12-18 19:00:25 +03:00
2005-06-01 13:49:30 +04:00
internal override TypeWrapper [ ] Interfaces
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
return interfaces ;
}
2002-12-18 19:00:25 +03:00
}
2005-06-01 13:49:30 +04:00
internal override TypeWrapper [ ] InnerClasses
2003-02-18 12:30:34 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
return impl . InnerClasses ;
}
2003-02-18 12:30:34 +03:00
}
2005-06-01 13:49:30 +04:00
internal override TypeWrapper DeclaringTypeWrapper
2003-02-18 12:30:34 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
return impl . DeclaringTypeWrapper ;
}
2003-02-18 12:30:34 +03:00
}
2005-06-01 13:49:30 +04:00
internal override Type TypeAsTBD
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
return impl . Type ;
}
2002-12-18 19:00:25 +03:00
}
2005-08-05 12:40:54 +04:00
internal override void Finish ( )
2003-01-02 16:46:16 +03:00
{
2005-06-01 13:49:30 +04:00
lock ( this )
2003-05-30 16:08:59 +04:00
{
2005-06-01 13:49:30 +04:00
Profiler . Enter ( "DynamicTypeWrapper.Finish" ) ;
try
{
2005-08-05 12:40:54 +04:00
impl = impl . Finish ( ) ;
2005-06-01 13:49:30 +04:00
}
finally
{
Profiler . Leave ( "DynamicTypeWrapper.Finish" ) ;
}
2003-05-30 16:08:59 +04:00
}
2005-06-01 13:49:30 +04:00
}
// NOTE can only be used if the type hasn't been finished yet!
internal FieldInfo ClassObjectField
{
get
2003-05-30 16:08:59 +04:00
{
2005-06-01 13:49:30 +04:00
return ( ( JavaTypeImpl ) impl ) . ClassObjectField ;
2003-05-30 16:08:59 +04:00
}
2003-01-02 16:46:16 +03:00
}
2002-12-18 19:00:25 +03:00
2005-06-01 13:49:30 +04:00
// NOTE can only be used if the type hasn't been finished yet!
protected string GenerateUniqueMethodName ( string basename , MethodWrapper mw )
2004-03-08 18:18:47 +03:00
{
2005-06-01 13:49:30 +04:00
return ( ( JavaTypeImpl ) impl ) . GenerateUniqueMethodName ( basename , mw ) ;
2004-03-08 18:18:47 +03:00
}
2004-09-17 13:32:06 +04:00
2005-06-01 13:49:30 +04:00
private abstract class DynamicImpl
{
internal abstract Type Type { get ; }
internal abstract TypeWrapper [ ] InnerClasses { get ; }
internal abstract TypeWrapper DeclaringTypeWrapper { get ; }
internal abstract Modifiers ReflectiveModifiers { get ; }
2005-08-05 12:40:54 +04:00
internal abstract DynamicImpl Finish ( ) ;
2005-06-01 13:49:30 +04:00
internal abstract MethodBase LinkMethod ( MethodWrapper mw ) ;
internal abstract FieldInfo LinkField ( FieldWrapper fw ) ;
2005-08-24 12:14:23 +04:00
internal abstract void EmitRunClassConstructor ( ILGenerator ilgen ) ;
2005-10-01 15:16:11 +04:00
internal abstract string GetGenericSignature ( ) ;
internal abstract string [ ] GetEnclosingMethod ( ) ;
internal abstract string GetGenericMethodSignature ( int index ) ;
internal abstract string GetGenericFieldSignature ( int index ) ;
2005-11-01 17:01:42 +03:00
internal abstract object [ ] GetDeclaredAnnotations ( ) ;
internal abstract object GetMethodDefaultValue ( int index ) ;
2006-04-19 19:49:54 +04:00
internal abstract object [ ] GetMethodAnnotations ( int index ) ;
internal abstract object [ ] [ ] GetParameterAnnotations ( int index ) ;
internal abstract object [ ] GetFieldAnnotations ( int index ) ;
2005-06-01 13:49:30 +04:00
}
2002-12-18 19:00:25 +03:00
2005-06-01 13:49:30 +04:00
private class JavaTypeImpl : DynamicImpl
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
private readonly ClassFile classFile ;
private readonly DynamicTypeWrapper wrapper ;
private readonly TypeBuilder typeBuilder ;
private MethodWrapper [ ] methods ;
private MethodWrapper [ ] baseMethods ;
private FieldWrapper [ ] fields ;
private FinishedTypeImpl finishedType ;
2005-08-03 16:59:16 +04:00
private readonly DynamicTypeWrapper outerClassWrapper ;
2005-06-01 13:49:30 +04:00
private Hashtable memberclashtable ;
private Hashtable classCache = new Hashtable ( ) ;
private FieldInfo classObjectField ;
2005-08-24 12:14:23 +04:00
private MethodBuilder clinitMethod ;
2006-04-10 13:09:09 +04:00
#if STATIC_COMPILER
2005-11-01 17:01:42 +03:00
private AnnotationBuilder annotationBuilder ;
2006-04-10 13:09:09 +04:00
#endif
2002-12-18 19:00:25 +03:00
2005-06-01 13:49:30 +04:00
internal JavaTypeImpl ( ClassFile f , DynamicTypeWrapper wrapper )
2003-02-20 17:18:38 +03:00
{
2005-06-01 13:49:30 +04:00
Tracer . Info ( Tracer . Compiler , "constructing JavaTypeImpl for " + f . Name ) ;
this . classFile = f ;
this . wrapper = wrapper ;
// process all methods
bool hasclinit = wrapper . BaseTypeWrapper = = null ? false : wrapper . BaseTypeWrapper . HasStaticInitializer ;
methods = new MethodWrapper [ classFile . Methods . Length ] ;
baseMethods = new MethodWrapper [ classFile . Methods . Length ] ;
for ( int i = 0 ; i < methods . Length ; i + + )
2004-09-15 17:35:44 +04:00
{
2005-06-01 13:49:30 +04:00
ClassFile . Method m = classFile . Methods [ i ] ;
if ( m . IsClassInitializer )
2004-09-15 17:35:44 +04:00
{
2006-04-10 13:09:09 +04:00
#if STATIC_COMPILER
if ( ! IsSideEffectFreeStaticInitializer ( m ) )
2004-09-15 17:35:44 +04:00
{
hasclinit = true ;
}
2006-04-10 13:09:09 +04:00
#else
hasclinit = true ;
#endif
2004-09-15 17:35:44 +04:00
}
2006-04-05 12:18:58 +04:00
MemberFlags flags = MemberFlags . None ;
if ( m . IsInternal )
{
flags | = MemberFlags . InternalAccess ;
}
2005-06-01 13:49:30 +04:00
if ( wrapper . IsGhost )
{
2006-04-05 12:18:58 +04:00
methods [ i ] = new MethodWrapper . GhostMethodWrapper ( wrapper , m . Name , m . Signature , null , null , null , m . Modifiers , flags ) ;
2005-06-01 13:49:30 +04:00
}
else if ( m . Name = = "<init>" )
{
2006-04-05 12:18:58 +04:00
methods [ i ] = new SmartConstructorMethodWrapper ( wrapper , m . Name , m . Signature , null , null , m . Modifiers , flags ) ;
2005-06-01 13:49:30 +04:00
}
2004-09-15 17:35:44 +04:00
else
{
2005-06-01 13:49:30 +04:00
if ( ! classFile . IsInterface & & ! m . IsStatic & & ! m . IsPrivate )
{
2006-04-05 12:18:58 +04:00
bool explicitOverride = false ;
2005-06-01 13:49:30 +04:00
baseMethods [ i ] = FindBaseMethod ( m . Name , m . Signature , out explicitOverride ) ;
2006-04-05 12:18:58 +04:00
if ( explicitOverride )
{
flags | = MemberFlags . ExplicitOverride ;
}
2005-06-01 13:49:30 +04:00
}
2006-04-05 12:18:58 +04:00
methods [ i ] = new SmartCallMethodWrapper ( wrapper , m . Name , m . Signature , null , null , null , m . Modifiers , flags , SimpleOpCode . Call , SimpleOpCode . Callvirt ) ;
2004-09-15 17:35:44 +04:00
}
}
2006-04-05 12:18:58 +04:00
wrapper . HasStaticInitializer = hasclinit ;
2005-08-14 19:49:50 +04:00
if ( ! wrapper . IsInterface )
2003-02-20 17:18:38 +03:00
{
2005-08-14 19:49:50 +04:00
ArrayList methodsArray = null ;
ArrayList baseMethodsArray = null ;
if ( wrapper . IsAbstract )
{
methodsArray = new ArrayList ( methods ) ;
baseMethodsArray = new ArrayList ( baseMethods ) ;
AddMirandaMethods ( methodsArray , baseMethodsArray , wrapper ) ;
}
2006-04-10 13:09:09 +04:00
#if STATIC_COMPILER
if ( wrapper . IsPublic )
2005-08-14 19:49:50 +04:00
{
TypeWrapper baseTypeWrapper = wrapper . BaseTypeWrapper ;
while ( baseTypeWrapper ! = null & & ! baseTypeWrapper . IsPublic )
{
if ( methodsArray = = null )
{
methodsArray = new ArrayList ( methods ) ;
baseMethodsArray = new ArrayList ( baseMethods ) ;
}
AddAccessStubMethods ( methodsArray , baseMethodsArray , baseTypeWrapper ) ;
baseTypeWrapper = baseTypeWrapper . BaseTypeWrapper ;
}
}
2006-04-10 13:09:09 +04:00
#endif
2005-08-14 19:49:50 +04:00
if ( methodsArray ! = null )
{
this . methods = ( MethodWrapper [ ] ) methodsArray . ToArray ( typeof ( MethodWrapper ) ) ;
this . baseMethods = ( MethodWrapper [ ] ) baseMethodsArray . ToArray ( typeof ( MethodWrapper ) ) ;
}
2003-02-20 17:18:38 +03:00
}
2005-06-01 13:49:30 +04:00
wrapper . SetMethods ( methods ) ;
fields = new FieldWrapper [ classFile . Fields . Length ] ;
for ( int i = 0 ; i < fields . Length ; i + + )
2003-02-20 17:18:38 +03:00
{
2005-06-01 13:49:30 +04:00
ClassFile . Field fld = classFile . Fields [ i ] ;
if ( fld . IsStatic & & fld . IsFinal & & fld . ConstantValue ! = null )
2004-08-17 13:05:21 +04:00
{
2005-08-14 19:49:50 +04:00
fields [ i ] = new ConstantFieldWrapper ( wrapper , null , fld . Name , fld . Signature , fld . Modifiers , null , fld . ConstantValue , MemberFlags . LiteralField ) ;
2005-06-01 13:49:30 +04:00
}
2005-07-07 17:10:09 +04:00
else if ( fld . IsFinal & & ( JVM . IsStaticCompiler & & ( fld . IsPublic | | fld . IsProtected ) )
& & ! wrapper . IsInterface & & ( ! JVM . StrictFinalFieldSemantics | | wrapper . Name = = "java.lang.System" ) )
2005-06-01 13:49:30 +04:00
{
2006-04-05 12:18:58 +04:00
fields [ i ] = new GetterFieldWrapper ( wrapper , null , null , fld . Name , fld . Signature , new ExModifiers ( fld . Modifiers , fld . IsInternal ) , null ) ;
2005-06-01 13:49:30 +04:00
}
else
{
2006-04-05 12:18:58 +04:00
fields [ i ] = FieldWrapper . Create ( wrapper , null , null , fld . Name , fld . Signature , new ExModifiers ( fld . Modifiers , fld . IsInternal ) ) ;
2004-08-17 13:05:21 +04:00
}
2005-01-03 11:26:21 +03:00
}
2006-04-10 13:09:09 +04:00
#if STATIC_COMPILER
if ( ! wrapper . IsInterface & & wrapper . IsPublic )
2005-08-14 19:49:50 +04:00
{
ArrayList fieldsArray = new ArrayList ( fields ) ;
AddAccessStubFields ( fieldsArray , wrapper ) ;
fields = ( FieldWrapper [ ] ) fieldsArray . ToArray ( typeof ( FieldWrapper ) ) ;
}
2006-04-10 13:09:09 +04:00
#endif
2005-06-01 13:49:30 +04:00
wrapper . SetFields ( fields ) ;
2004-08-17 13:05:21 +04:00
2005-06-01 13:49:30 +04:00
// from now on we shouldn't be throwing any exceptions (to be precise, after we've
// called ModuleBuilder.DefineType)
try
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
TypeAttributes typeAttribs = 0 ;
if ( f . IsAbstract )
2003-10-17 12:08:31 +04:00
{
2005-06-01 13:49:30 +04:00
typeAttribs | = TypeAttributes . Abstract ;
}
if ( f . IsFinal )
{
typeAttribs | = TypeAttributes . Sealed ;
}
if ( ! hasclinit )
{
typeAttribs | = TypeAttributes . BeforeFieldInit ;
}
TypeBuilder outer = null ;
// only if requested, we compile inner classes as nested types, because it has a higher cost
// and doesn't buy us anything, unless we're compiling a library that could be used from C# (e.g.)
if ( JVM . CompileInnerClassesAsNestedTypes )
{
2005-08-03 16:59:16 +04:00
string outerClassName = getOuterClassName ( ) ;
if ( outerClassName ! = null )
2004-08-17 13:05:21 +04:00
{
2005-08-03 16:59:16 +04:00
if ( ! CheckInnerOuterNames ( f . Name , outerClassName ) )
2005-06-01 13:49:30 +04:00
{
Tracer . Warning ( Tracer . Compiler , "Incorrect InnerClasses attribute on {0}" , f . Name ) ;
}
else
2004-08-17 13:05:21 +04:00
{
2005-08-03 16:59:16 +04:00
try
{
outerClassWrapper = wrapper . GetClassLoader ( ) . LoadClassByDottedNameFast ( outerClassName ) as DynamicTypeWrapper ;
}
2005-08-25 11:46:57 +04:00
catch ( RetargetableJavaException x )
2005-06-01 13:49:30 +04:00
{
2005-08-03 16:59:16 +04:00
Tracer . Warning ( Tracer . Compiler , "Unable to load outer class {0} for innner class {1} ({2}: {3})" , outerClassName , f . Name , x . GetType ( ) . Name , x . Message ) ;
}
if ( outerClassWrapper ! = null )
{
// make sure the relationship is reciprocal (otherwise we run the risk of
// baking the outer type before the inner type)
lock ( outerClassWrapper )
{
if ( outerClassWrapper . impl is JavaTypeImpl )
{
ClassFile outerClassFile = ( ( JavaTypeImpl ) outerClassWrapper . impl ) . classFile ;
ClassFile . InnerClass [ ] outerInnerClasses = outerClassFile . InnerClasses ;
if ( outerInnerClasses = = null )
{
outerClassWrapper = null ;
}
else
{
bool ok = false ;
for ( int i = 0 ; i < outerInnerClasses . Length ; i + + )
{
if ( outerInnerClasses [ i ] . outerClass ! = 0
& & outerClassFile . GetConstantPoolClass ( outerInnerClasses [ i ] . outerClass ) = = outerClassFile . Name
& & outerInnerClasses [ i ] . innerClass ! = 0
& & outerClassFile . GetConstantPoolClass ( outerInnerClasses [ i ] . innerClass ) = = f . Name )
{
ok = true ;
break ;
}
}
if ( ! ok )
{
outerClassWrapper = null ;
}
}
}
else
{
outerClassWrapper = null ;
}
}
if ( outerClassWrapper ! = null )
{
outer = outerClassWrapper . TypeAsBuilder ;
}
else
{
Tracer . Warning ( Tracer . Compiler , "Non-reciprocal inner class {0}" , f . Name ) ;
}
2005-06-01 13:49:30 +04:00
}
2004-08-17 13:05:21 +04:00
}
}
2003-10-17 12:08:31 +04:00
}
2006-04-05 12:18:58 +04:00
if ( f . IsPublic )
2003-10-17 12:08:31 +04:00
{
2005-06-01 13:49:30 +04:00
if ( outer ! = null )
{
typeAttribs | = TypeAttributes . NestedPublic ;
}
else
{
typeAttribs | = TypeAttributes . Public ;
}
2003-10-17 12:08:31 +04:00
}
2005-06-01 13:49:30 +04:00
else if ( outer ! = null )
2003-10-17 12:08:31 +04:00
{
2005-06-01 13:49:30 +04:00
typeAttribs | = TypeAttributes . NestedAssembly ;
2003-10-17 12:08:31 +04:00
}
2005-06-01 13:49:30 +04:00
if ( f . IsInterface )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
typeAttribs | = TypeAttributes . Interface | TypeAttributes . Abstract ;
if ( outer ! = null )
{
if ( wrapper . IsGhost )
{
// TODO this is low priority, since the current Java class library doesn't define any ghost interfaces
// as inner classes
throw new NotImplementedException ( ) ;
}
// LAMESPEC the CLI spec says interfaces cannot contain nested types (Part.II, 9.6), but that rule isn't enforced
// (and broken by J# as well), so we'll just ignore it too.
typeBuilder = outer . DefineNestedType ( GetInnerClassName ( outerClassWrapper . Name , f . Name ) , typeAttribs ) ;
}
else
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
typeBuilder = wrapper . DefineType ( typeAttribs ) ;
2004-08-17 13:05:21 +04:00
}
}
else
{
2005-06-01 13:49:30 +04:00
typeAttribs | = TypeAttributes . Class ;
if ( outer ! = null )
{
// LAMESPEC the CLI spec says interfaces cannot contain nested types (Part.II, 9.6), but that rule isn't enforced
// (and broken by J# as well), so we'll just ignore it too.
typeBuilder = outer . DefineNestedType ( GetInnerClassName ( outerClassWrapper . Name , f . Name ) , typeAttribs , wrapper . BaseTypeWrapper . TypeAsBaseType ) ;
}
else
{
2006-03-23 14:57:41 +03:00
typeBuilder = wrapper . classLoader . ModuleBuilder . DefineType ( wrapper . classLoader . MangleTypeName ( f . Name ) , typeAttribs , wrapper . BaseTypeWrapper . TypeAsBaseType ) ;
2005-06-01 13:49:30 +04:00
}
2004-08-17 13:05:21 +04:00
}
2005-12-19 18:12:49 +03:00
ArrayList interfaceList = null ;
2005-06-01 13:49:30 +04:00
TypeWrapper [ ] interfaces = wrapper . Interfaces ;
for ( int i = 0 ; i < interfaces . Length ; i + + )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
// NOTE we're using TypeAsBaseType for the interfaces!
typeBuilder . AddInterfaceImplementation ( interfaces [ i ] . TypeAsBaseType ) ;
2005-12-19 18:12:49 +03:00
// NOTE we're also "implementing" all interfaces that we inherit from the interfaces we implement.
// The C# compiler also does this and the Compact Framework requires it.
TypeWrapper [ ] inheritedInterfaces = interfaces [ i ] . Interfaces ;
if ( inheritedInterfaces . Length > 0 )
{
if ( interfaceList = = null )
{
interfaceList = new ArrayList ( ) ;
foreach ( TypeWrapper tw1 in interfaces )
{
interfaceList . Add ( tw1 . TypeAsBaseType ) ;
}
}
foreach ( TypeWrapper tw in inheritedInterfaces )
{
if ( ! interfaceList . Contains ( tw . TypeAsBaseType ) )
{
interfaceList . Add ( tw . TypeAsBaseType ) ;
// NOTE we don't have to recurse upwards, because we assume that
// all interfaces follow this rule (of explicitly listed all of the base interfaces)
typeBuilder . AddInterfaceImplementation ( tw . TypeAsBaseType ) ;
}
}
}
2004-08-17 13:05:21 +04:00
}
2005-06-01 13:49:30 +04:00
AttributeHelper . SetImplementsAttribute ( typeBuilder , interfaces ) ;
2006-02-22 17:44:07 +03:00
if ( JVM . IsStaticCompiler | | DynamicClassLoader . IsSaveDebugImage )
2004-08-17 13:05:21 +04:00
{
2005-10-01 15:16:11 +04:00
if ( classFile . DeprecatedAttribute )
{
AttributeHelper . SetDeprecatedAttribute ( typeBuilder ) ;
}
if ( classFile . GenericSignature ! = null )
{
AttributeHelper . SetSignatureAttribute ( typeBuilder , classFile . GenericSignature ) ;
}
if ( classFile . EnclosingMethod ! = null )
{
AttributeHelper . SetEnclosingMethodAttribute ( typeBuilder , classFile . EnclosingMethod [ 0 ] , classFile . EnclosingMethod [ 1 ] , classFile . EnclosingMethod [ 2 ] ) ;
}
2005-06-01 13:49:30 +04:00
}
2005-07-07 15:24:08 +04:00
if ( ! JVM . NoStackTraceInfo )
2005-06-01 13:49:30 +04:00
{
2005-07-07 15:24:08 +04:00
if ( f . SourceFileAttribute ! = null )
{
if ( f . SourceFileAttribute ! = typeBuilder . Name + ".java" )
{
AttributeHelper . SetSourceFile ( typeBuilder , f . SourceFileAttribute ) ;
}
}
else
{
AttributeHelper . SetSourceFile ( typeBuilder , null ) ;
}
2004-08-17 13:05:21 +04:00
}
2005-08-24 12:14:23 +04:00
if ( ! classFile . IsInterface & & hasclinit )
{
// We create a empty method that we can use to trigger our .cctor
// (previously we used RuntimeHelpers.RunClassConstructor, but that is slow and requires additional privileges)
MethodAttributes attribs = MethodAttributes . Static | MethodAttributes . SpecialName ;
if ( classFile . IsAbstract )
{
bool hasfields = false ;
// If we have any public static fields, the cctor trigger must (and may) be public as well
foreach ( ClassFile . Field fld in classFile . Fields )
{
if ( fld . IsPublic & & fld . IsStatic )
{
hasfields = true ;
break ;
}
}
attribs | = hasfields ? MethodAttributes . Public : MethodAttributes . FamORAssem ;
}
else
{
attribs | = MethodAttributes . Public ;
}
clinitMethod = typeBuilder . DefineMethod ( "__<clinit>" , attribs , null , null ) ;
clinitMethod . GetILGenerator ( ) . Emit ( OpCodes . Ret ) ;
}
2006-04-10 13:09:09 +04:00
#if STATIC_COMPILER
if ( f . IsAnnotation )
2005-11-01 17:01:42 +03:00
{
annotationBuilder = new AnnotationBuilder ( this ) ;
( ( AotTypeWrapper ) wrapper ) . SetAnnotation ( annotationBuilder ) ;
}
2006-04-10 13:09:09 +04:00
#endif
2004-08-17 13:05:21 +04:00
}
2005-06-01 13:49:30 +04:00
catch ( Exception x )
2004-10-19 17:43:55 +04:00
{
2005-06-01 13:49:30 +04:00
if ( typeBuilder ! = null )
{
JVM . CriticalFailure ( "Exception during critical part of JavaTypeImpl construction" , x ) ;
}
throw ;
2004-10-19 17:43:55 +04:00
}
2002-12-29 19:27:00 +03:00
}
2005-06-01 13:49:30 +04:00
2005-08-03 16:59:16 +04:00
private string getOuterClassName ( )
{
ClassFile . InnerClass [ ] innerClasses = classFile . InnerClasses ;
if ( innerClasses ! = null )
{
for ( int j = 0 ; j < innerClasses . Length ; j + + )
{
if ( innerClasses [ j ] . outerClass ! = 0
& & innerClasses [ j ] . innerClass ! = 0
& & classFile . GetConstantPoolClass ( innerClasses [ j ] . innerClass ) = = classFile . Name )
{
return classFile . GetConstantPoolClass ( innerClasses [ j ] . outerClass ) ;
}
}
}
return null ;
}
2006-04-14 18:11:39 +04:00
#if STATIC_COMPILER
2005-06-01 13:49:30 +04:00
private bool IsSideEffectFreeStaticInitializer ( ClassFile . Method m )
2002-12-29 19:27:00 +03:00
{
2005-06-01 13:49:30 +04:00
if ( m . ExceptionTable . Length ! = 0 )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
return false ;
2004-08-17 13:05:21 +04:00
}
2005-06-01 13:49:30 +04:00
for ( int i = 0 ; i < m . Instructions . Length ; i + + )
2004-09-15 17:35:44 +04:00
{
2005-07-20 14:47:59 +04:00
NormalizedByteCode bc = m . Instructions [ i ] . NormalizedOpCode ;
if ( bc = = NormalizedByteCode . __getstatic | | bc = = NormalizedByteCode . __putstatic )
2005-06-01 13:49:30 +04:00
{
ClassFile . ConstantPoolItemFieldref fld = classFile . GetFieldref ( m . Instructions [ i ] . Arg1 ) ;
if ( fld . Class ! = classFile . Name )
{
return false ;
}
// don't allow getstatic to load non-primitive fields, because that would
// cause the verifier to try to load the type
2005-07-20 14:47:59 +04:00
if ( bc = = NormalizedByteCode . __getstatic & & "L[" . IndexOf ( fld . Signature [ 0 ] ) ! = - 1 )
2005-06-01 13:49:30 +04:00
{
return false ;
}
}
2005-07-20 14:47:59 +04:00
else if ( bc = = NormalizedByteCode . __areturn | |
bc = = NormalizedByteCode . __ireturn | |
bc = = NormalizedByteCode . __lreturn | |
bc = = NormalizedByteCode . __freturn | |
bc = = NormalizedByteCode . __dreturn )
2004-09-15 17:35:44 +04:00
{
return false ;
}
2005-06-01 13:49:30 +04:00
else if ( ByteCodeMetaData . CanThrowException ( bc ) )
2004-09-15 17:35:44 +04:00
{
return false ;
}
}
2005-06-01 13:49:30 +04:00
// the method needs to be verifiable to be side effect free, since we already analysed it,
// we know that the verifier won't try to load any types (which isn't allowed at this time)
try
2004-09-15 17:35:44 +04:00
{
2005-06-01 13:49:30 +04:00
new MethodAnalyzer ( wrapper , null , classFile , m , null ) ;
return true ;
2004-09-15 17:35:44 +04:00
}
2005-06-01 13:49:30 +04:00
catch ( VerifyError )
2004-09-15 17:35:44 +04:00
{
return false ;
}
}
2006-04-14 18:11:39 +04:00
#endif // STATIC_COMPILER
2004-09-15 17:35:44 +04:00
2005-08-14 19:49:50 +04:00
private static bool ContainsMemberWrapper ( ArrayList members , string name , string sig )
{
foreach ( MemberWrapper mw in members )
{
if ( mw . Name = = name & & mw . Signature = = sig )
{
return true ;
}
}
return false ;
}
2005-06-01 13:49:30 +04:00
private MethodWrapper GetMethodWrapperDuringCtor ( TypeWrapper lookup , ArrayList methods , string name , string sig )
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
if ( lookup = = wrapper )
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
foreach ( MethodWrapper mw in methods )
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
if ( mw . Name = = name & & mw . Signature = = sig )
{
return mw ;
}
}
if ( lookup . BaseTypeWrapper = = null )
{
return null ;
}
else
{
return lookup . BaseTypeWrapper . GetMethodWrapper ( name , sig , true ) ;
2005-01-03 11:26:21 +03:00
}
}
else
{
2005-06-01 13:49:30 +04:00
return lookup . GetMethodWrapper ( name , sig , true ) ;
2005-01-03 11:26:21 +03:00
}
}
2005-06-01 13:49:30 +04:00
private void AddMirandaMethods ( ArrayList methods , ArrayList baseMethods , TypeWrapper tw )
2003-11-17 15:01:50 +03:00
{
2005-06-01 13:49:30 +04:00
foreach ( TypeWrapper iface in tw . Interfaces )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
AddMirandaMethods ( methods , baseMethods , iface ) ;
foreach ( MethodWrapper ifmethod in iface . GetMethods ( ) )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
// skip <clinit>
if ( ! ifmethod . IsStatic )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
TypeWrapper lookup = wrapper ;
while ( lookup ! = null )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
MethodWrapper mw = GetMethodWrapperDuringCtor ( lookup , methods , ifmethod . Name , ifmethod . Signature ) ;
if ( mw = = null )
{
mw = new SmartCallMethodWrapper ( wrapper , ifmethod . Name , ifmethod . Signature , null , null , null , Modifiers . Public | Modifiers . Abstract , MemberFlags . HideFromReflection | MemberFlags . MirandaMethod , SimpleOpCode . Call , SimpleOpCode . Callvirt ) ;
methods . Add ( mw ) ;
baseMethods . Add ( ifmethod ) ;
break ;
}
if ( ! mw . IsStatic )
{
break ;
}
lookup = mw . DeclaringType . BaseTypeWrapper ;
2004-08-17 13:05:21 +04:00
}
}
}
}
2003-11-17 15:01:50 +03:00
}
2003-02-20 17:18:38 +03:00
2005-08-14 19:49:50 +04:00
private void AddAccessStubMethods ( ArrayList methods , ArrayList baseMethods , TypeWrapper tw )
{
foreach ( MethodWrapper mw in tw . GetMethods ( ) )
{
if ( ( mw . IsPublic | | mw . IsProtected )
& & mw . Name ! = "<init>"
& & ! ContainsMemberWrapper ( methods , mw . Name , mw . Signature ) )
{
MethodWrapper stub = new SmartCallMethodWrapper ( wrapper , mw . Name , mw . Signature , null , null , null , mw . Modifiers , MemberFlags . HideFromReflection | MemberFlags . AccessStub , SimpleOpCode . Call , SimpleOpCode . Callvirt ) ;
methods . Add ( stub ) ;
baseMethods . Add ( mw ) ;
}
}
}
private void AddAccessStubFields ( ArrayList fields , TypeWrapper tw )
{
do
{
if ( ! tw . IsPublic )
{
foreach ( FieldWrapper fw in tw . GetFields ( ) )
{
if ( ( fw . IsPublic | | fw . IsProtected )
& & ! ContainsMemberWrapper ( fields , fw . Name , fw . Signature ) )
{
fields . Add ( new AotAccessStubFieldWrapper ( wrapper , fw ) ) ;
}
}
}
foreach ( TypeWrapper iface in tw . Interfaces )
{
AddAccessStubFields ( fields , iface ) ;
}
tw = tw . BaseTypeWrapper ;
} while ( tw ! = null & & ! tw . IsPublic ) ;
}
2005-06-01 13:49:30 +04:00
private static bool CheckInnerOuterNames ( string inner , string outer )
{
// do some sanity checks on the inner/outer class names
return inner . Length > outer . Length + 1 & & inner [ outer . Length ] = = '$' & & inner . IndexOf ( '$' , outer . Length + 1 ) = = - 1 ;
}
2002-12-18 19:00:25 +03:00
2005-06-01 13:49:30 +04:00
private static string GetInnerClassName ( string outer , string inner )
2003-11-17 15:01:50 +03:00
{
2005-06-01 13:49:30 +04:00
Debug . Assert ( CheckInnerOuterNames ( inner , outer ) ) ;
return inner . Substring ( outer . Length + 1 ) ;
2003-11-17 15:01:50 +03:00
}
2005-06-01 13:49:30 +04:00
private static bool IsCompatibleArgList ( TypeWrapper [ ] caller , TypeWrapper [ ] callee )
2003-12-20 01:19:18 +03:00
{
2005-06-01 13:49:30 +04:00
if ( caller . Length = = callee . Length )
2003-12-20 01:19:18 +03:00
{
2005-06-01 13:49:30 +04:00
for ( int i = 0 ; i < caller . Length ; i + + )
2003-12-20 01:19:18 +03:00
{
2005-06-01 13:49:30 +04:00
if ( ! caller [ i ] . IsAssignableTo ( callee [ i ] ) )
2003-12-20 01:19:18 +03:00
{
2005-06-01 13:49:30 +04:00
return false ;
2003-12-20 01:19:18 +03:00
}
}
2005-06-01 13:49:30 +04:00
return true ;
2003-12-20 01:19:18 +03:00
}
2005-06-01 13:49:30 +04:00
return false ;
2003-12-20 01:19:18 +03:00
}
2005-06-01 13:49:30 +04:00
private void EmitConstantValueInitialization ( ILGenerator ilGenerator )
2004-09-17 13:32:06 +04:00
{
2005-06-01 13:49:30 +04:00
ClassFile . Field [ ] fields = classFile . Fields ;
for ( int i = 0 ; i < fields . Length ; i + + )
2004-09-17 13:32:06 +04:00
{
2005-06-01 13:49:30 +04:00
ClassFile . Field f = fields [ i ] ;
if ( f . IsStatic & & ! f . IsFinal )
2004-09-17 13:32:06 +04:00
{
2005-06-01 13:49:30 +04:00
object constant = f . ConstantValue ;
if ( constant ! = null )
{
if ( constant is int )
{
ilGenerator . Emit ( OpCodes . Ldc_I4 , ( int ) constant ) ;
}
else if ( constant is long )
{
ilGenerator . Emit ( OpCodes . Ldc_I8 , ( long ) constant ) ;
}
else if ( constant is double )
{
ilGenerator . Emit ( OpCodes . Ldc_R8 , ( double ) constant ) ;
}
else if ( constant is float )
{
ilGenerator . Emit ( OpCodes . Ldc_R4 , ( float ) constant ) ;
}
else if ( constant is string )
{
ilGenerator . Emit ( OpCodes . Ldstr , ( string ) constant ) ;
}
else
{
throw new InvalidOperationException ( ) ;
}
this . fields [ i ] . EmitSet ( ilGenerator ) ;
}
2004-09-17 13:32:06 +04:00
}
}
}
2005-06-01 13:49:30 +04:00
internal FieldInfo ClassObjectField
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
get
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
lock ( this )
{
if ( classObjectField = = null )
{
2005-07-07 18:03:21 +04:00
classObjectField = typeBuilder . DefineField ( "__<classObject>" , typeof ( object ) , FieldAttributes . Private | FieldAttributes . Static | FieldAttributes . SpecialName ) ;
2005-06-01 13:49:30 +04:00
}
return classObjectField ;
}
2005-01-03 11:26:21 +03:00
}
}
2005-06-01 13:49:30 +04:00
private int GetMethodIndex ( MethodWrapper mw )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
for ( int i = 0 ; i < methods . Length ; i + + )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
if ( methods [ i ] = = mw )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
return i ;
2004-08-17 13:05:21 +04:00
}
}
2005-06-01 13:49:30 +04:00
throw new InvalidOperationException ( ) ;
}
internal override MethodBase LinkMethod ( MethodWrapper mw )
{
Debug . Assert ( mw ! = null ) ;
bool unloadableOverrideStub = false ;
int index = GetMethodIndex ( mw ) ;
MethodWrapper baseMethod = baseMethods [ index ] ;
if ( baseMethod ! = null )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
baseMethod . Link ( ) ;
// check the loader constraints
if ( mw . ReturnType ! = baseMethod . ReturnType )
2004-08-17 13:05:21 +04:00
{
2005-08-05 12:40:54 +04:00
if ( baseMethod . ReturnType . IsUnloadable | | JVM . FinishingForDebugSave )
2004-08-17 13:05:21 +04:00
{
2005-08-05 12:40:54 +04:00
if ( ! mw . ReturnType . IsUnloadable | | ( ! baseMethod . ReturnType . IsUnloadable & & JVM . FinishingForDebugSave ) )
2004-08-17 13:05:21 +04:00
{
unloadableOverrideStub = true ;
}
}
else
{
throw new LinkageError ( "Loader constraints violated" ) ;
}
}
2005-06-01 13:49:30 +04:00
TypeWrapper [ ] here = mw . GetParameters ( ) ;
TypeWrapper [ ] there = baseMethod . GetParameters ( ) ;
for ( int i = 0 ; i < here . Length ; i + + )
{
if ( here [ i ] ! = there [ i ] )
{
2005-08-05 12:40:54 +04:00
if ( there [ i ] . IsUnloadable | | JVM . FinishingForDebugSave )
2005-06-01 13:49:30 +04:00
{
2005-08-05 12:40:54 +04:00
if ( ! here [ i ] . IsUnloadable | | ( ! there [ i ] . IsUnloadable & & JVM . FinishingForDebugSave ) )
2005-06-01 13:49:30 +04:00
{
unloadableOverrideStub = true ;
}
}
else
{
throw new LinkageError ( "Loader constraints violated" ) ;
}
}
}
2004-08-17 13:05:21 +04:00
}
2005-06-01 13:49:30 +04:00
Debug . Assert ( mw . GetMethod ( ) = = null ) ;
MethodBase mb = GenerateMethod ( index , unloadableOverrideStub ) ;
if ( ( mw . Modifiers & ( Modifiers . Synchronized | Modifiers . Static ) ) = = Modifiers . Synchronized )
{
// note that constructors cannot be synchronized in Java
MethodBuilder mbld = ( MethodBuilder ) mb ;
mbld . SetImplementationFlags ( mbld . GetMethodImplementationFlags ( ) | MethodImplAttributes . Synchronized ) ;
}
return mb ;
2004-08-17 13:05:21 +04:00
}
2005-06-01 13:49:30 +04:00
private int GetFieldIndex ( FieldWrapper fw )
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
for ( int i = 0 ; i < fields . Length ; i + + )
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
if ( fields [ i ] = = fw )
{
return i ;
}
2005-01-03 11:26:21 +03:00
}
2005-06-01 13:49:30 +04:00
throw new InvalidOperationException ( ) ;
2005-01-03 11:26:21 +03:00
}
2005-06-01 13:49:30 +04:00
internal override FieldInfo LinkField ( FieldWrapper fw )
2005-01-03 11:26:21 +03:00
{
2005-08-14 19:49:50 +04:00
if ( fw . IsAccessStub )
{
( ( AotAccessStubFieldWrapper ) fw ) . DoLink ( typeBuilder ) ;
return null ;
}
2005-06-01 13:49:30 +04:00
FieldBuilder field ;
ClassFile . Field fld = classFile . Fields [ GetFieldIndex ( fw ) ] ;
string fieldName = fld . Name ;
TypeWrapper typeWrapper = fw . FieldTypeWrapper ;
Type type = typeWrapper . TypeAsSignatureType ;
bool setNameSig = typeWrapper . IsUnloadable | | typeWrapper . IsGhostArray ;
if ( setNameSig )
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
// TODO use clashtable
// the field name is mangled here, because otherwise it can (theoretically)
// conflict with another unloadable or object or ghost array field
// (fields can be overloaded on type)
fieldName + = "/" + typeWrapper . Name ;
}
FieldAttributes attribs = 0 ;
2005-09-01 11:34:53 +04:00
MethodAttributes methodAttribs = MethodAttributes . HideBySig ;
2005-06-01 13:49:30 +04:00
bool setModifiers = false ;
if ( fld . IsPrivate )
{
attribs | = FieldAttributes . Private ;
2005-01-03 11:26:21 +03:00
}
2005-06-01 13:49:30 +04:00
else if ( fld . IsProtected )
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
attribs | = FieldAttributes . FamORAssem ;
methodAttribs | = MethodAttributes . FamORAssem ;
2005-01-03 11:26:21 +03:00
}
2006-04-05 12:18:58 +04:00
else if ( fld . IsPublic )
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
attribs | = FieldAttributes . Public ;
methodAttribs | = MethodAttributes . Public ;
2005-01-03 11:26:21 +03:00
}
2005-06-01 13:49:30 +04:00
else
{
attribs | = FieldAttributes . Assembly ;
methodAttribs | = MethodAttributes . Assembly ;
}
if ( fld . IsStatic )
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
attribs | = FieldAttributes . Static ;
methodAttribs | = MethodAttributes . Static ;
2005-01-03 11:26:21 +03:00
}
2005-06-01 13:49:30 +04:00
// NOTE "constant" static finals are converted into literals
// TODO it would be possible for Java code to change the value of a non-blank static final, but I don't
// know if we want to support this (since the Java JITs don't really support it either)
object constantValue = fld . ConstantValue ;
if ( fld . IsStatic & & fld . IsFinal & & constantValue ! = null )
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
Profiler . Count ( "Static Final Constant" ) ;
attribs | = FieldAttributes . Literal ;
field = typeBuilder . DefineField ( fieldName , type , attribs ) ;
field . SetConstant ( constantValue ) ;
2005-01-03 11:26:21 +03:00
}
2005-06-01 13:49:30 +04:00
else
2005-01-03 11:26:21 +03:00
{
2005-07-07 17:10:09 +04:00
bool isWrappedFinal = fw is GetterFieldWrapper ;
if ( fld . IsFinal )
2005-01-03 11:26:21 +03:00
{
2005-07-07 17:10:09 +04:00
if ( isWrappedFinal )
2005-06-01 13:49:30 +04:00
{
// NOTE public/protected blank final fields get converted into a read-only property with a private field
// backing store
// we used to make the field privatescope, but that really serves no purpose (and it hinders
// serialization, which uses .NET reflection to get at the field)
attribs & = ~ FieldAttributes . FieldAccessMask ;
attribs | = FieldAttributes . Private ;
setModifiers = true ;
}
2005-07-07 17:10:09 +04:00
else if ( wrapper . IsInterface | | JVM . StrictFinalFieldSemantics )
{
attribs | = FieldAttributes . InitOnly ;
}
else
{
setModifiers = true ;
}
2005-06-01 13:49:30 +04:00
}
field = typeBuilder . DefineField ( fieldName , type , attribs ) ;
if ( fld . IsTransient )
{
CustomAttributeBuilder transientAttrib = new CustomAttributeBuilder ( typeof ( NonSerializedAttribute ) . GetConstructor ( Type . EmptyTypes ) , new object [ 0 ] ) ;
field . SetCustomAttribute ( transientAttrib ) ;
}
if ( fld . IsVolatile )
{
// TODO the field should be marked as modreq(IsVolatile), but Reflection.Emit doesn't have a way of doing this
setModifiers = true ;
}
// Instance fields can also have a ConstantValue attribute (and are inlined by the compiler),
// and ikvmstub has to export them, so we have to add a custom attribute.
if ( constantValue ! = null )
{
2005-12-07 12:06:32 +03:00
AttributeHelper . SetConstantValue ( field , constantValue ) ;
2005-06-01 13:49:30 +04:00
}
if ( isWrappedFinal )
{
methodAttribs | = MethodAttributes . SpecialName ;
// TODO we should ensure that the getter method name doesn't clash with an existing method
MethodBuilder getter = typeBuilder . DefineMethod ( "get_" + fld . Name , methodAttribs , CallingConventions . Standard , type , Type . EmptyTypes ) ;
AttributeHelper . HideFromJava ( getter ) ;
ILGenerator ilgen = getter . GetILGenerator ( ) ;
if ( fld . IsStatic )
{
ilgen . Emit ( OpCodes . Ldsfld , field ) ;
}
else
{
ilgen . Emit ( OpCodes . Ldarg_0 ) ;
ilgen . Emit ( OpCodes . Ldfld , field ) ;
}
ilgen . Emit ( OpCodes . Ret ) ;
PropertyBuilder pb = typeBuilder . DefineProperty ( fld . Name , PropertyAttributes . None , type , Type . EmptyTypes ) ;
pb . SetGetMethod ( getter ) ;
( ( GetterFieldWrapper ) fw ) . SetGetter ( getter ) ;
2005-01-03 11:26:21 +03:00
}
}
2006-02-22 17:44:07 +03:00
if ( JVM . IsStaticCompiler | | DynamicClassLoader . IsSaveDebugImage )
2005-06-01 13:49:30 +04:00
{
2005-10-01 15:16:11 +04:00
// if the Java modifiers cannot be expressed in .NET, we emit the Modifiers attribute to store
// the Java modifiers
2006-04-05 12:18:58 +04:00
if ( setModifiers | | fld . IsInternal | | ( fld . Modifiers & ( Modifiers . Synthetic | Modifiers . Enum ) ) ! = 0 )
2005-10-01 15:16:11 +04:00
{
2006-04-05 12:18:58 +04:00
AttributeHelper . SetModifiers ( field , fld . Modifiers , fld . IsInternal ) ;
2005-10-01 15:16:11 +04:00
}
if ( setNameSig )
{
AttributeHelper . SetNameSig ( field , fld . Name , fld . Signature ) ;
}
if ( fld . DeprecatedAttribute )
{
AttributeHelper . SetDeprecatedAttribute ( field ) ;
}
if ( fld . GenericSignature ! = null )
{
AttributeHelper . SetSignatureAttribute ( field , fld . GenericSignature ) ;
}
2005-06-01 13:49:30 +04:00
}
return field ;
2005-01-03 11:26:21 +03:00
}
2004-08-17 13:05:21 +04:00
2005-08-24 12:14:23 +04:00
internal override void EmitRunClassConstructor ( ILGenerator ilgen )
{
if ( clinitMethod ! = null )
{
ilgen . Emit ( OpCodes . Call , clinitMethod ) ;
}
}
2005-08-05 12:40:54 +04:00
internal override DynamicImpl Finish ( )
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
if ( wrapper . BaseTypeWrapper ! = null )
{
2005-08-05 12:40:54 +04:00
wrapper . BaseTypeWrapper . Finish ( ) ;
2005-06-01 13:49:30 +04:00
}
if ( outerClassWrapper ! = null )
{
2005-08-05 12:40:54 +04:00
outerClassWrapper . Finish ( ) ;
2005-06-01 13:49:30 +04:00
}
// NOTE there is a bug in the CLR (.NET 1.0 & 1.1 [1.2 is not yet available]) that
// causes the AppDomain.TypeResolve event to receive the incorrect type name for nested types.
// The Name in the ResolveEventArgs contains only the nested type name, not the full type name,
// for example, if the type being resolved is "MyOuterType+MyInnerType", then the event only
// receives "MyInnerType" as the name. Since we only compile inner classes as nested types
// when we're statically compiling, we can only run into this bug when we're statically compiling.
// NOTE To work around this bug, we have to make sure that all types that are going to be
// required in finished form, are finished explicitly here. It isn't clear what other types are
// required to be finished. I instrumented a static compilation of classpath.dll and this
// turned up no other cases of the TypeResolve event firing.
for ( int i = 0 ; i < wrapper . Interfaces . Length ; i + + )
{
2005-08-05 12:40:54 +04:00
wrapper . Interfaces [ i ] . Finish ( ) ;
2005-06-01 13:49:30 +04:00
}
// make sure all classes are loaded, before we start finishing the type. During finishing, we
// may not run any Java code, because that might result in a request to finish the type that we
// are in the process of finishing, and this would be a problem.
classFile . Link ( wrapper , classCache ) ;
for ( int i = 0 ; i < fields . Length ; i + + )
{
fields [ i ] . Link ( ) ;
}
for ( int i = 0 ; i < methods . Length ; i + + )
{
methods [ i ] . Link ( ) ;
}
// it is possible that the loading of the referenced classes triggered a finish of us,
// if that happens, we just return
if ( finishedType ! = null )
{
return finishedType ;
}
Profiler . Enter ( "JavaTypeImpl.Finish.Core" ) ;
try
2003-10-17 12:08:31 +04:00
{
2005-06-01 13:49:30 +04:00
TypeWrapper declaringTypeWrapper = null ;
TypeWrapper [ ] innerClassesTypeWrappers = TypeWrapper . EmptyArray ;
// if we're an inner class, we need to attach an InnerClass attribute
ClassFile . InnerClass [ ] innerclasses = classFile . InnerClasses ;
if ( innerclasses ! = null )
2003-10-17 12:08:31 +04:00
{
2005-06-01 13:49:30 +04:00
// TODO consider not pre-computing innerClassesTypeWrappers and declaringTypeWrapper here
ArrayList wrappers = new ArrayList ( ) ;
for ( int i = 0 ; i < innerclasses . Length ; i + + )
2003-10-17 12:08:31 +04:00
{
2005-06-01 13:49:30 +04:00
if ( innerclasses [ i ] . innerClass ! = 0 & & innerclasses [ i ] . outerClass ! = 0 )
2003-10-17 12:08:31 +04:00
{
2005-06-01 13:49:30 +04:00
if ( classFile . GetConstantPoolClassType ( innerclasses [ i ] . outerClass ) = = wrapper )
{
wrappers . Add ( classFile . GetConstantPoolClassType ( innerclasses [ i ] . innerClass ) ) ;
}
if ( classFile . GetConstantPoolClassType ( innerclasses [ i ] . innerClass ) = = wrapper )
{
declaringTypeWrapper = classFile . GetConstantPoolClassType ( innerclasses [ i ] . outerClass ) ;
2005-07-07 15:24:08 +04:00
string inner = classFile . GetConstantPoolClass ( innerclasses [ i ] . innerClass ) ;
if ( inner = = classFile . Name & & inner = = declaringTypeWrapper . Name + "$" + typeBuilder . Name )
{
inner = null ;
}
AttributeHelper . SetInnerClass ( typeBuilder , inner , innerclasses [ i ] . accessFlags ) ;
2005-06-01 13:49:30 +04:00
}
2003-10-17 12:08:31 +04:00
}
}
2005-06-01 13:49:30 +04:00
innerClassesTypeWrappers = ( TypeWrapper [ ] ) wrappers . ToArray ( typeof ( TypeWrapper ) ) ;
2003-10-17 12:08:31 +04:00
}
2005-06-01 13:49:30 +04:00
wrapper . FinishGhost ( typeBuilder , methods ) ;
// if we're not abstract make sure we don't inherit any abstract methods
if ( ! wrapper . IsAbstract )
2003-10-17 12:08:31 +04:00
{
2005-06-01 13:49:30 +04:00
TypeWrapper parent = wrapper . BaseTypeWrapper ;
// if parent is not abstract, the .NET implementation will never have abstract methods (only
// stubs that throw AbstractMethodError)
// NOTE interfaces are supposed to be abstract, but the VM doesn't enforce this, so
// we have to check for a null parent (interfaces have no parent).
while ( parent ! = null & & parent . IsAbstract )
2003-10-17 12:08:31 +04:00
{
2005-06-01 13:49:30 +04:00
foreach ( MethodWrapper mw in parent . GetMethods ( ) )
{
MethodInfo mi = mw . GetMethod ( ) as MethodInfo ;
2005-10-02 00:22:45 +04:00
if ( mi ! = null & & mi . IsAbstract & & wrapper . GetMethodWrapper ( mw . Name , mw . Signature , true ) = = mw )
2005-06-01 13:49:30 +04:00
{
// NOTE in Sun's JRE 1.4.1 this method cannot be overridden by subclasses,
// but I think this is a bug, so we'll support it anyway.
MethodBuilder mb = typeBuilder . DefineMethod ( mi . Name , mi . Attributes & ~ ( MethodAttributes . Abstract | MethodAttributes . NewSlot ) , CallingConventions . Standard , mw . ReturnTypeForDefineMethod , mw . GetParametersForDefineMethod ( ) ) ;
AttributeHelper . HideFromJava ( mb ) ;
EmitHelper . Throw ( mb . GetILGenerator ( ) , "java.lang.AbstractMethodError" , wrapper . Name + "." + mw . Name + mw . Signature ) ;
}
}
parent = parent . BaseTypeWrapper ;
2003-01-02 18:44:17 +03:00
}
2002-12-18 19:00:25 +03:00
}
2005-12-07 12:06:32 +03:00
Hashtable invokespecialstubcache = new Hashtable ( ) ;
2005-06-01 13:49:30 +04:00
bool basehasclinit = wrapper . BaseTypeWrapper ! = null & & wrapper . BaseTypeWrapper . HasStaticInitializer ;
bool hasclinit = false ;
for ( int i = 0 ; i < classFile . Methods . Length ; i + + )
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
ClassFile . Method m = classFile . Methods [ i ] ;
MethodBase mb = methods [ i ] . GetMethod ( ) ;
if ( mb is ConstructorBuilder )
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
ILGenerator ilGenerator = ( ( ConstructorBuilder ) mb ) . GetILGenerator ( ) ;
2006-04-10 13:09:09 +04:00
TraceHelper . EmitMethodTrace ( ilGenerator , classFile . Name + "." + m . Name + m . Signature ) ;
2005-06-01 13:49:30 +04:00
if ( basehasclinit & & m . IsClassInitializer & & ! classFile . IsInterface )
2003-01-02 18:44:17 +03:00
{
2005-06-01 13:49:30 +04:00
hasclinit = true ;
// before we call the base class initializer, we need to set the non-final static ConstantValue fields
EmitConstantValueInitialization ( ilGenerator ) ;
2005-08-24 12:14:23 +04:00
wrapper . BaseTypeWrapper . EmitRunClassConstructor ( ilGenerator ) ;
2002-12-18 19:00:25 +03:00
}
2005-12-07 12:06:32 +03:00
Compiler . Compile ( wrapper , methods [ i ] , classFile , m , ilGenerator , invokespecialstubcache ) ;
2004-08-17 13:05:21 +04:00
}
2005-06-01 13:49:30 +04:00
else
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
if ( m . IsAbstract )
2005-05-27 16:44:06 +04:00
{
2005-06-01 13:49:30 +04:00
// NOTE in the JVM it is apparently legal for a non-abstract class to have abstract methods, but
// the CLR doens't allow this, so we have to emit a method that throws an AbstractMethodError
if ( ! classFile . IsAbstract )
{
ILGenerator ilGenerator = ( ( MethodBuilder ) mb ) . GetILGenerator ( ) ;
2006-04-10 13:09:09 +04:00
TraceHelper . EmitMethodTrace ( ilGenerator , classFile . Name + "." + m . Name + m . Signature ) ;
2005-06-01 13:49:30 +04:00
EmitHelper . Throw ( ilGenerator , "java.lang.AbstractMethodError" , classFile . Name + "." + m . Name + m . Signature ) ;
}
2005-05-27 16:44:06 +04:00
}
2005-06-01 13:49:30 +04:00
else if ( m . IsNative )
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
if ( ( mb . Attributes & MethodAttributes . PinvokeImpl ) ! = 0 )
2003-11-17 15:01:50 +03:00
{
2005-05-30 19:30:13 +04:00
continue ;
2003-11-17 15:01:50 +03:00
}
2005-06-01 13:49:30 +04:00
Profiler . Enter ( "JavaTypeImpl.Finish.Native" ) ;
try
2003-11-17 15:01:50 +03:00
{
2005-06-01 13:49:30 +04:00
ILGenerator ilGenerator = ( ( MethodBuilder ) mb ) . GetILGenerator ( ) ;
2006-04-10 13:09:09 +04:00
TraceHelper . EmitMethodTrace ( ilGenerator , classFile . Name + "." + m . Name + m . Signature ) ;
2005-06-01 13:49:30 +04:00
// do we have a native implementation in map.xml?
if ( wrapper . EmitMapXmlMethodBody ( ilGenerator , classFile , m ) )
2003-11-17 15:01:50 +03:00
{
2005-06-01 13:49:30 +04:00
continue ;
2003-11-17 15:01:50 +03:00
}
2005-06-01 13:49:30 +04:00
// see if there exists a IKVM.NativeCode class for this type
2006-04-10 13:09:09 +04:00
Type nativeCodeType = null ;
#if STATIC_COMPILER
nativeCodeType = StaticCompiler . GetType ( "IKVM.NativeCode." + classFile . Name . Replace ( '$' , '+' ) , false ) ;
#endif
2005-06-01 13:49:30 +04:00
MethodInfo nativeMethod = null ;
TypeWrapper [ ] args = methods [ i ] . GetParameters ( ) ;
if ( nativeCodeType ! = null )
2003-11-17 15:01:50 +03:00
{
2005-06-01 13:49:30 +04:00
TypeWrapper [ ] nargs = args ;
if ( ! m . IsStatic )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
nargs = new TypeWrapper [ args . Length + 1 ] ;
args . CopyTo ( nargs , 1 ) ;
nargs [ 0 ] = this . wrapper ;
2004-08-17 13:05:21 +04:00
}
2005-06-01 13:49:30 +04:00
MethodInfo [ ] nativeCodeTypeMethods = nativeCodeType . GetMethods ( BindingFlags . Static | BindingFlags . Public ) ;
foreach ( MethodInfo method in nativeCodeTypeMethods )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
ParameterInfo [ ] param = method . GetParameters ( ) ;
TypeWrapper [ ] match = new TypeWrapper [ param . Length ] ;
for ( int j = 0 ; j < param . Length ; j + + )
{
match [ j ] = ClassLoaderWrapper . GetWrapperFromType ( param [ j ] . ParameterType ) ;
}
if ( m . Name = = method . Name & & IsCompatibleArgList ( nargs , match ) )
{
// TODO instead of taking the first matching method, we should find the best one
nativeMethod = method ;
break ;
}
2004-08-17 13:05:21 +04:00
}
2003-11-17 15:01:50 +03:00
}
2005-06-01 13:49:30 +04:00
if ( nativeMethod ! = null )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
int add = 0 ;
if ( ! m . IsStatic )
{
ilGenerator . Emit ( OpCodes . Ldarg_0 ) ;
add = 1 ;
}
for ( int j = 0 ; j < args . Length ; j + + )
{
ilGenerator . Emit ( OpCodes . Ldarg_S , ( byte ) ( j + add ) ) ;
}
ilGenerator . Emit ( OpCodes . Call , nativeMethod ) ;
TypeWrapper retTypeWrapper = methods [ i ] . ReturnType ;
if ( ! retTypeWrapper . TypeAsTBD . Equals ( nativeMethod . ReturnType ) & & ! retTypeWrapper . IsGhost )
{
ilGenerator . Emit ( OpCodes . Castclass , retTypeWrapper . TypeAsTBD ) ;
}
ilGenerator . Emit ( OpCodes . Ret ) ;
2004-08-17 13:05:21 +04:00
}
else
{
2005-06-01 13:49:30 +04:00
if ( JVM . NoJniStubs )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
// since NoJniStubs can only be set when we're statically compiling, it is safe to use the "compiler" trace switch
Tracer . Warning ( Tracer . Compiler , "Native method not implemented: {0}.{1}.{2}" , classFile . Name , m . Name , m . Signature ) ;
EmitHelper . Throw ( ilGenerator , "java.lang.UnsatisfiedLinkError" , "Native method not implemented (compiled with -nojni): " + classFile . Name + "." + m . Name + m . Signature ) ;
2004-08-17 13:05:21 +04:00
}
else
{
2006-02-22 17:44:07 +03:00
if ( DynamicClassLoader . IsSaveDebugImage )
2005-06-01 13:49:30 +04:00
{
JniProxyBuilder . Generate ( ilGenerator , wrapper , methods [ i ] , typeBuilder , classFile , m , args ) ;
}
else
{
JniBuilder . Generate ( ilGenerator , wrapper , methods [ i ] , typeBuilder , classFile , m , args , false ) ;
}
2004-08-17 13:05:21 +04:00
}
}
2003-01-02 18:44:17 +03:00
}
2005-06-01 13:49:30 +04:00
finally
{
Profiler . Leave ( "JavaTypeImpl.Finish.Native" ) ;
}
2003-01-02 18:44:17 +03:00
}
2005-06-01 13:49:30 +04:00
else
2005-03-01 11:24:54 +03:00
{
2005-06-01 13:49:30 +04:00
MethodBuilder mbld = ( MethodBuilder ) mb ;
ILGenerator ilGenerator = mbld . GetILGenerator ( ) ;
2006-04-10 13:09:09 +04:00
TraceHelper . EmitMethodTrace ( ilGenerator , classFile . Name + "." + m . Name + m . Signature ) ;
2005-06-01 13:49:30 +04:00
if ( wrapper . EmitMapXmlMethodBody ( ilGenerator , classFile , m ) )
{
continue ;
}
bool nonleaf = false ;
2005-12-07 12:06:32 +03:00
Compiler . Compile ( wrapper , methods [ i ] , classFile , m , ilGenerator , ref nonleaf , invokespecialstubcache ) ;
2005-06-01 13:49:30 +04:00
if ( nonleaf )
{
mbld . SetImplementationFlags ( mbld . GetMethodImplementationFlags ( ) | MethodImplAttributes . NoInlining ) ;
}
2005-03-01 11:24:54 +03:00
}
2002-12-27 12:01:16 +03:00
}
2003-01-02 18:44:17 +03:00
}
2005-06-01 13:49:30 +04:00
// NOTE non-final fields aren't allowed in interfaces so we don't have to initialize constant fields
if ( ! classFile . IsInterface )
2003-05-30 16:08:59 +04:00
{
2005-06-01 13:49:30 +04:00
// if we don't have a <clinit> we may need to inject one
if ( ! hasclinit )
2003-12-20 01:19:18 +03:00
{
2005-06-01 13:49:30 +04:00
bool hasconstantfields = false ;
if ( ! basehasclinit )
2003-12-20 01:19:18 +03:00
{
2005-06-01 13:49:30 +04:00
foreach ( ClassFile . Field f in classFile . Fields )
2003-12-20 01:19:18 +03:00
{
2005-06-01 13:49:30 +04:00
if ( f . IsStatic & & ! f . IsFinal & & f . ConstantValue ! = null )
{
hasconstantfields = true ;
break ;
}
2003-12-20 01:19:18 +03:00
}
}
2005-06-01 13:49:30 +04:00
if ( basehasclinit | | hasconstantfields )
2003-12-20 01:19:18 +03:00
{
2005-06-01 13:49:30 +04:00
ConstructorBuilder cb = DefineClassInitializer ( ) ;
AttributeHelper . HideFromJava ( cb ) ;
ILGenerator ilGenerator = cb . GetILGenerator ( ) ;
EmitConstantValueInitialization ( ilGenerator ) ;
if ( basehasclinit )
{
2005-08-24 12:14:23 +04:00
wrapper . BaseTypeWrapper . EmitRunClassConstructor ( ilGenerator ) ;
2005-06-01 13:49:30 +04:00
}
ilGenerator . Emit ( OpCodes . Ret ) ;
2003-12-20 01:19:18 +03:00
}
}
2003-05-30 16:08:59 +04:00
2005-06-01 13:49:30 +04:00
// here we loop thru all the interfaces to explicitly implement any methods that we inherit from
// base types that may have a different name from the name in the interface
// (e.g. interface that has an equals() method that should override System.Object.Equals())
// also deals with interface methods that aren't implemented (generate a stub that throws AbstractMethodError)
// and with methods that aren't public (generate a stub that throws IllegalAccessError)
Hashtable doneSet = new Hashtable ( ) ;
TypeWrapper [ ] interfaces = wrapper . Interfaces ;
for ( int i = 0 ; i < interfaces . Length ; i + + )
2003-10-17 12:08:31 +04:00
{
2006-04-10 13:09:09 +04:00
#if STATIC_COMPILER
2005-06-01 13:49:30 +04:00
// if we implement a ghost interface, add an implicit conversion to the ghost reference value type
// TODO do this for indirectly implemented interfaces (interfaces implemented by interfaces) as well
2006-04-10 13:09:09 +04:00
if ( interfaces [ i ] . IsGhost & & wrapper . IsPublic )
2005-06-01 13:49:30 +04:00
{
2005-09-01 11:34:53 +04:00
MethodBuilder mb = typeBuilder . DefineMethod ( "op_Implicit" , MethodAttributes . HideBySig | MethodAttributes . Public | MethodAttributes . Static | MethodAttributes . SpecialName , interfaces [ i ] . TypeAsSignatureType , new Type [ ] { wrapper . TypeAsSignatureType } ) ;
2005-06-01 13:49:30 +04:00
ILGenerator ilgen = mb . GetILGenerator ( ) ;
LocalBuilder local = ilgen . DeclareLocal ( interfaces [ i ] . TypeAsSignatureType ) ;
ilgen . Emit ( OpCodes . Ldloca , local ) ;
ilgen . Emit ( OpCodes . Ldarg_0 ) ;
ilgen . Emit ( OpCodes . Stfld , interfaces [ i ] . GhostRefField ) ;
ilgen . Emit ( OpCodes . Ldloca , local ) ;
ilgen . Emit ( OpCodes . Ldobj , interfaces [ i ] . TypeAsSignatureType ) ;
ilgen . Emit ( OpCodes . Ret ) ;
}
2006-04-10 13:09:09 +04:00
#endif
2005-06-01 13:49:30 +04:00
interfaces [ i ] . ImplementInterfaceMethodStubs ( typeBuilder , wrapper , doneSet ) ;
2003-10-17 12:08:31 +04:00
}
2005-06-01 13:49:30 +04:00
// if any of our base classes has an incomplete interface implementation we need to look through all
// the base class interfaces to see if we've got an implementation now
TypeWrapper baseTypeWrapper = wrapper . BaseTypeWrapper ;
while ( baseTypeWrapper . HasIncompleteInterfaceImplementation )
2003-05-13 00:00:15 +04:00
{
2005-06-01 13:49:30 +04:00
for ( int i = 0 ; i < baseTypeWrapper . Interfaces . Length ; i + + )
{
baseTypeWrapper . Interfaces [ i ] . ImplementInterfaceMethodStubs ( typeBuilder , wrapper , doneSet ) ;
}
baseTypeWrapper = baseTypeWrapper . BaseTypeWrapper ;
2003-05-13 00:00:15 +04:00
}
2005-06-01 13:49:30 +04:00
foreach ( MethodWrapper mw in methods )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
if ( mw . Name ! = "<init>" & & ! mw . IsStatic & & ! mw . IsPrivate )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
if ( wrapper . BaseTypeWrapper ! = null & & wrapper . BaseTypeWrapper . HasIncompleteInterfaceImplementation )
{
Hashtable hashtable = null ;
TypeWrapper tw = wrapper . BaseTypeWrapper ;
while ( tw . HasIncompleteInterfaceImplementation )
{
foreach ( TypeWrapper iface in tw . Interfaces )
{
AddMethodOverride ( mw , ( MethodBuilder ) mw . GetMethod ( ) , iface , mw . Name , mw . Signature , ref hashtable , false ) ;
}
tw = tw . BaseTypeWrapper ;
}
}
if ( true )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
Hashtable hashtable = null ;
foreach ( TypeWrapper iface in wrapper . Interfaces )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
AddMethodOverride ( mw , ( MethodBuilder ) mw . GetMethod ( ) , iface , mw . Name , mw . Signature , ref hashtable , true ) ;
2004-08-17 13:05:21 +04:00
}
}
}
2005-06-01 13:49:30 +04:00
}
}
2006-04-10 13:09:09 +04:00
#if STATIC_COMPILER
2005-06-01 13:49:30 +04:00
// If we're an interface that has public/protected fields, we create an inner class
// to expose these fields to C# (which stubbornly refuses to see fields in interfaces).
TypeBuilder tbFields = null ;
2006-04-10 13:09:09 +04:00
if ( classFile . IsInterface & & classFile . IsPublic & & ! wrapper . IsGhost & & classFile . Fields . Length > 0 )
2005-06-01 13:49:30 +04:00
{
// TODO handle name clash
tbFields = typeBuilder . DefineNestedType ( "__Fields" , TypeAttributes . Class | TypeAttributes . NestedPublic | TypeAttributes . Sealed ) ;
tbFields . DefineDefaultConstructor ( MethodAttributes . Private ) ;
AttributeHelper . HideFromJava ( tbFields ) ;
ILGenerator ilgenClinit = null ;
foreach ( ClassFile . Field f in classFile . Fields )
{
TypeWrapper typeWrapper = ClassFile . FieldTypeWrapperFromSig ( wrapper . GetClassLoader ( ) , classCache , f . Signature ) ;
if ( f . ConstantValue ! = null )
{
FieldAttributes attribs = FieldAttributes . Public | FieldAttributes . Static | FieldAttributes . Literal ;
FieldBuilder fb = tbFields . DefineField ( f . Name , typeWrapper . TypeAsSignatureType , attribs ) ;
fb . SetConstant ( f . ConstantValue ) ;
}
else
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
FieldAttributes attribs = FieldAttributes . Public | FieldAttributes . Static | FieldAttributes . InitOnly ;
FieldBuilder fb = tbFields . DefineField ( f . Name , typeWrapper . TypeAsSignatureType , attribs ) ;
if ( ilgenClinit = = null )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
ilgenClinit = tbFields . DefineTypeInitializer ( ) . GetILGenerator ( ) ;
2004-08-17 13:05:21 +04:00
}
2005-06-01 13:49:30 +04:00
wrapper . GetFieldWrapper ( f . Name , f . Signature ) . EmitGet ( ilgenClinit ) ;
ilgenClinit . Emit ( OpCodes . Stsfld , fb ) ;
2004-08-17 13:05:21 +04:00
}
}
2005-06-01 13:49:30 +04:00
if ( ilgenClinit ! = null )
{
ilgenClinit . Emit ( OpCodes . Ret ) ;
}
2004-08-17 13:05:21 +04:00
}
2002-12-18 19:00:25 +03:00
2005-06-01 13:49:30 +04:00
// See if there is any additional metadata
wrapper . EmitMapXmlMetadata ( typeBuilder , classFile , fields , methods ) ;
2005-11-01 17:01:42 +03:00
TypeBuilder enumBuilder = null ;
2006-04-10 13:09:09 +04:00
if ( true )
2005-10-01 15:16:11 +04:00
{
// NOTE in Whidbey we can (and should) use CompilerGeneratedAttribute to mark Synthetic types
2006-04-05 12:18:58 +04:00
if ( classFile . IsInternal | | ( classFile . Modifiers & ( Modifiers . Synthetic | Modifiers . Annotation | Modifiers . Enum ) ) ! = 0 )
2005-10-01 15:16:11 +04:00
{
2006-04-05 12:18:58 +04:00
AttributeHelper . SetModifiers ( typeBuilder , classFile . Modifiers , classFile . IsInternal ) ;
2005-10-01 15:16:11 +04:00
}
2005-11-01 17:01:42 +03:00
// // For Java 5 Enum types, we generate a nested .NET enum
// if(classFile.IsEnum)
// {
// // TODO if wrapper is inner class, the Enum should be defined as an innerclass as well
// enumBuilder = wrapper.GetClassLoader().ModuleBuilder.DefineType(classFile.Name + "Enum", TypeAttributes.Class | TypeAttributes.Sealed | TypeAttributes.Public | TypeAttributes.Serializable, typeof(Enum));
// AttributeHelper.HideFromJava(enumBuilder);
// enumBuilder.DefineField("value__", typeof(int), FieldAttributes.Public | FieldAttributes.SpecialName | FieldAttributes.RTSpecialName);
// for(int i = 0; i < classFile.Fields.Length; i++)
// {
// if(classFile.Fields[i].IsEnum)
// {
// FieldBuilder fieldBuilder = enumBuilder.DefineField(classFile.Fields[i].Name, enumBuilder, FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.Literal);
// fieldBuilder.SetConstant(i);
// }
// }
// }
if ( classFile . Annotations ! = null )
{
foreach ( object [ ] def in classFile . Annotations )
{
Debug . Assert ( def [ 0 ] . Equals ( AnnotationDefaultAttribute . TAG_ANNOTATION ) ) ;
string annotationClass = ( string ) def [ 1 ] ;
Annotation annotation = null ;
try
{
TypeWrapper annot = wrapper . GetClassLoader ( ) . RetTypeWrapperFromSig ( annotationClass . Replace ( '/' , '.' ) ) ;
annotation = annot . Annotation ;
}
catch ( RetargetableJavaException )
{
Tracer . Warning ( Tracer . Compiler , "Unable to load annotation class {0}" , annotationClass ) ;
}
if ( annotation = = null )
{
// TODO figure out what to do here
}
else
{
annotation . Apply ( typeBuilder , def ) ;
}
}
}
2005-10-01 15:16:11 +04:00
}
2006-04-10 13:09:09 +04:00
#endif // STATIC_COMPILER
2005-10-01 15:16:11 +04:00
2005-06-01 13:49:30 +04:00
Type type ;
Profiler . Enter ( "TypeBuilder.CreateType" ) ;
try
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
type = typeBuilder . CreateType ( ) ;
2006-04-10 13:09:09 +04:00
#if STATIC_COMPILER
2005-06-01 13:49:30 +04:00
if ( tbFields ! = null )
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
tbFields . CreateType ( ) ;
2005-01-03 11:26:21 +03:00
}
2005-11-01 17:01:42 +03:00
if ( enumBuilder ! = null )
{
enumBuilder . CreateType ( ) ;
}
if ( annotationBuilder ! = null )
{
annotationBuilder . Finish ( this ) ;
}
2006-04-10 13:09:09 +04:00
#endif
2005-01-03 11:26:21 +03:00
}
2005-06-01 13:49:30 +04:00
finally
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
Profiler . Leave ( "TypeBuilder.CreateType" ) ;
2005-01-03 11:26:21 +03:00
}
2005-06-01 13:49:30 +04:00
ClassLoaderWrapper . SetWrapperForType ( type , wrapper ) ;
2005-07-27 19:57:55 +04:00
wrapper . FinishGhostStep2 ( ) ;
2005-08-03 16:59:16 +04:00
BakedTypeCleanupHack . Process ( wrapper ) ;
2005-11-01 17:01:42 +03:00
finishedType = new FinishedTypeImpl ( type , innerClassesTypeWrappers , declaringTypeWrapper , this . ReflectiveModifiers , Metadata . Create ( classFile ) ) ;
return finishedType ;
}
catch ( Exception x )
{
JVM . CriticalFailure ( "Exception during finishing of: " + wrapper . Name , x ) ;
return null ;
}
finally
{
Profiler . Leave ( "JavaTypeImpl.Finish.Core" ) ;
}
}
2006-04-10 13:09:09 +04:00
class TraceHelper
{
private readonly static MethodInfo methodIsTracedMethod = typeof ( Tracer ) . GetMethod ( "IsTracedMethod" ) ;
private readonly static MethodInfo methodMethodInfo = typeof ( Tracer ) . GetMethod ( "MethodInfo" ) ;
internal static void EmitMethodTrace ( ILGenerator ilgen , string tracemessage )
{
if ( Tracer . IsTracedMethod ( tracemessage ) )
{
Label label = ilgen . DefineLabel ( ) ;
#if STATIC_COMPILER
// TODO this should be a boolean field test instead of a call to Tracer.IsTracedMessage
ilgen . Emit ( OpCodes . Ldstr , tracemessage ) ;
ilgen . Emit ( OpCodes . Call , methodIsTracedMethod ) ;
ilgen . Emit ( OpCodes . Brfalse_S , label ) ;
#endif
ilgen . Emit ( OpCodes . Ldstr , tracemessage ) ;
ilgen . Emit ( OpCodes . Call , methodMethodInfo ) ;
ilgen . MarkLabel ( label ) ;
}
}
}
2005-11-01 17:01:42 +03:00
private bool IsValidAnnotationElementType ( string type )
{
if ( type [ 0 ] = = '[' )
{
type = type . Substring ( 1 ) ;
}
switch ( type )
{
case "Z" :
case "B" :
case "S" :
case "C" :
case "I" :
case "J" :
case "F" :
case "D" :
case "Ljava.lang.String;" :
case "Ljava.lang.Class;" :
return true ;
}
if ( type . StartsWith ( "L" ) & & type . EndsWith ( ";" ) )
{
try
2005-10-01 15:16:11 +04:00
{
2005-11-01 17:01:42 +03:00
TypeWrapper tw = wrapper . GetClassLoader ( ) . LoadClassByDottedNameFast ( type . Substring ( 1 , type . Length - 2 ) ) ;
if ( tw ! = null )
2005-10-01 15:16:11 +04:00
{
2005-11-01 17:01:42 +03:00
if ( ( tw . Modifiers & Modifiers . Annotation ) ! = 0 )
2005-10-01 15:16:11 +04:00
{
2005-11-01 17:01:42 +03:00
return true ;
}
if ( ( tw . Modifiers & Modifiers . Enum ) ! = 0 )
{
TypeWrapper enumType = ClassLoaderWrapper . GetBootstrapClassLoader ( ) . LoadClassByDottedNameFast ( "java.lang.Enum" ) ;
if ( enumType ! = null & & tw . IsSubTypeOf ( enumType ) )
{
return true ;
}
2005-10-01 15:16:11 +04:00
}
}
}
2005-11-01 17:01:42 +03:00
catch
2005-10-01 15:16:11 +04:00
{
2005-11-01 17:01:42 +03:00
}
}
return false ;
}
2006-04-14 18:11:39 +04:00
#if STATIC_COMPILER
2005-11-01 17:01:42 +03:00
sealed class AnnotationBuilder : Annotation
{
private TypeBuilder annotationTypeBuilder ;
private TypeBuilder attributeTypeBuilder ;
private ConstructorBuilder defaultConstructor ;
private ConstructorBuilder defineConstructor ;
internal AnnotationBuilder ( JavaTypeImpl o )
{
// Make sure the annotation type only has valid methods
for ( int i = 0 ; i < o . methods . Length ; i + + )
{
if ( ! o . methods [ i ] . IsStatic )
2005-10-01 15:16:11 +04:00
{
2005-11-01 17:01:42 +03:00
if ( ! o . methods [ i ] . Signature . StartsWith ( "()" ) )
{
return ;
}
if ( ! o . IsValidAnnotationElementType ( o . methods [ i ] . Signature . Substring ( 2 ) ) )
2005-10-01 15:16:11 +04:00
{
2005-11-01 17:01:42 +03:00
return ;
2005-10-01 15:16:11 +04:00
}
}
}
2005-11-01 17:01:42 +03:00
2006-04-05 15:04:43 +04:00
// we only set annotationTypeBuilder if we're valid
annotationTypeBuilder = o . typeBuilder ;
2005-11-01 17:01:42 +03:00
TypeWrapper annotationAttributeBaseType = ClassLoaderWrapper . LoadClassCritical ( "ikvm.internal.AnnotationAttributeBase" ) ;
// TODO attribute should be .NET serializable
TypeAttributes typeAttributes = TypeAttributes . Class | TypeAttributes . Sealed ;
if ( o . outerClassWrapper ! = null )
2005-10-01 15:16:11 +04:00
{
2005-11-01 17:01:42 +03:00
if ( o . wrapper . IsPublic )
2005-10-01 15:16:11 +04:00
{
2005-11-01 17:01:42 +03:00
typeAttributes | = TypeAttributes . NestedPublic ;
2005-10-01 15:16:11 +04:00
}
2005-11-01 17:01:42 +03:00
else
{
typeAttributes | = TypeAttributes . NestedAssembly ;
}
attributeTypeBuilder = o . outerClassWrapper . TypeAsBuilder . DefineNestedType ( GetInnerClassName ( o . outerClassWrapper . Name , o . classFile . Name ) + "Attribute" , typeAttributes , annotationAttributeBaseType . TypeAsBaseType ) ;
2005-10-01 15:16:11 +04:00
}
2005-11-01 17:01:42 +03:00
else
2005-10-01 15:16:11 +04:00
{
2005-11-01 17:01:42 +03:00
if ( o . wrapper . IsPublic )
{
typeAttributes | = TypeAttributes . Public ;
}
else
2005-10-01 15:16:11 +04:00
{
2005-11-01 17:01:42 +03:00
typeAttributes | = TypeAttributes . NotPublic ;
2005-10-01 15:16:11 +04:00
}
2006-03-23 14:57:41 +03:00
attributeTypeBuilder = o . wrapper . classLoader . ModuleBuilder . DefineType ( o . classFile . Name + "Attribute" , typeAttributes , annotationAttributeBaseType . TypeAsBaseType ) ;
2005-10-01 15:16:11 +04:00
}
2005-11-01 17:01:42 +03:00
if ( o . wrapper . IsPublic )
{
// In the Java world, the class appears as a non-public proxy class
2006-04-05 12:18:58 +04:00
AttributeHelper . SetModifiers ( attributeTypeBuilder , Modifiers . Final , false ) ;
2005-11-01 17:01:42 +03:00
}
// NOTE we "abuse" the InnerClassAttribute to add a custom attribute to name the class "$Proxy[Annotation]" in the Java world
int dotindex = o . classFile . Name . LastIndexOf ( '.' ) + 1 ;
AttributeHelper . SetInnerClass ( attributeTypeBuilder , o . classFile . Name . Substring ( 0 , dotindex ) + "$Proxy" + o . classFile . Name . Substring ( dotindex ) , Modifiers . Final ) ;
attributeTypeBuilder . AddInterfaceImplementation ( o . typeBuilder ) ;
CustomAttributeBuilder cab = new CustomAttributeBuilder ( typeof ( AnnotationAttributeAttribute ) . GetConstructor ( new Type [ ] { typeof ( string ) } ) , new object [ ] { attributeTypeBuilder . FullName } ) ;
o . typeBuilder . SetCustomAttribute ( cab ) ;
defaultConstructor = attributeTypeBuilder . DefineConstructor ( MethodAttributes . Public , CallingConventions . Standard , Type . EmptyTypes ) ;
defineConstructor = attributeTypeBuilder . DefineConstructor ( MethodAttributes . Public , CallingConventions . Standard , new Type [ ] { typeof ( object [ ] ) } ) ;
2002-12-29 19:27:00 +03:00
}
2005-11-01 17:01:42 +03:00
internal void Finish ( JavaTypeImpl o )
2004-12-21 13:26:51 +03:00
{
2006-04-05 15:04:43 +04:00
if ( annotationTypeBuilder = = null )
{
// not a valid annotation type
return ;
}
2005-11-01 17:01:42 +03:00
TypeWrapper annotationAttributeBaseType = ClassLoaderWrapper . LoadClassCritical ( "ikvm.internal.AnnotationAttributeBase" ) ;
annotationAttributeBaseType . Finish ( ) ;
ILGenerator ilgen = defaultConstructor . GetILGenerator ( ) ;
ilgen . Emit ( OpCodes . Ldarg_0 ) ;
ilgen . Emit ( OpCodes . Ldtoken , annotationTypeBuilder ) ;
2006-04-11 16:05:24 +04:00
ilgen . Emit ( OpCodes . Call , ByteCodeHelperMethods . GetClassFromTypeHandle ) ;
2005-11-01 17:01:42 +03:00
CoreClasses . java . lang . Class . Wrapper . EmitCheckcast ( null , ilgen ) ;
annotationAttributeBaseType . GetMethodWrapper ( "<init>" , "(Ljava.lang.Class;)V" , false ) . EmitCall ( ilgen ) ;
ilgen . Emit ( OpCodes . Ret ) ;
ilgen = defineConstructor . GetILGenerator ( ) ;
ilgen . Emit ( OpCodes . Ldarg_0 ) ;
ilgen . Emit ( OpCodes . Call , defaultConstructor ) ;
ilgen . Emit ( OpCodes . Ldarg_0 ) ;
ilgen . Emit ( OpCodes . Ldarg_1 ) ;
annotationAttributeBaseType . GetMethodWrapper ( "setDefinition" , "([Ljava.lang.Object;)V" , false ) . EmitCall ( ilgen ) ;
ilgen . Emit ( OpCodes . Ret ) ;
MethodWrapper getValueMethod = annotationAttributeBaseType . GetMethodWrapper ( "getValue" , "(Ljava.lang.String;)Ljava.lang.Object;" , false ) ;
MethodWrapper getByteValueMethod = annotationAttributeBaseType . GetMethodWrapper ( "getByteValue" , "(Ljava.lang.String;)B" , false ) ;
MethodWrapper getBooleanValueMethod = annotationAttributeBaseType . GetMethodWrapper ( "getBooleanValue" , "(Ljava.lang.String;)Z" , false ) ;
MethodWrapper getCharValueMethod = annotationAttributeBaseType . GetMethodWrapper ( "getCharValue" , "(Ljava.lang.String;)C" , false ) ;
MethodWrapper getShortValueMethod = annotationAttributeBaseType . GetMethodWrapper ( "getShortValue" , "(Ljava.lang.String;)S" , false ) ;
MethodWrapper getIntValueMethod = annotationAttributeBaseType . GetMethodWrapper ( "getIntValue" , "(Ljava.lang.String;)I" , false ) ;
MethodWrapper getFloatValueMethod = annotationAttributeBaseType . GetMethodWrapper ( "getFloatValue" , "(Ljava.lang.String;)F" , false ) ;
MethodWrapper getLongValueMethod = annotationAttributeBaseType . GetMethodWrapper ( "getLongValue" , "(Ljava.lang.String;)J" , false ) ;
MethodWrapper getDoubleValueMethod = annotationAttributeBaseType . GetMethodWrapper ( "getDoubleValue" , "(Ljava.lang.String;)D" , false ) ;
for ( int i = 0 ; i < o . methods . Length ; i + + )
{
// skip <clinit>
if ( ! o . methods [ i ] . IsStatic )
{
MethodBuilder mb = attributeTypeBuilder . DefineMethod ( o . methods [ i ] . Name , MethodAttributes . Public | MethodAttributes . Virtual | MethodAttributes . Final | MethodAttributes . NewSlot , o . methods [ i ] . ReturnTypeForDefineMethod , o . methods [ i ] . GetParametersForDefineMethod ( ) ) ;
ilgen = mb . GetILGenerator ( ) ;
ilgen . Emit ( OpCodes . Ldarg_0 ) ;
ilgen . Emit ( OpCodes . Ldstr , o . methods [ i ] . Name ) ;
if ( o . methods [ i ] . ReturnType . IsPrimitive )
{
if ( o . methods [ i ] . ReturnType = = PrimitiveTypeWrapper . BYTE )
{
getByteValueMethod . EmitCall ( ilgen ) ;
}
else if ( o . methods [ i ] . ReturnType = = PrimitiveTypeWrapper . BOOLEAN )
{
getBooleanValueMethod . EmitCall ( ilgen ) ;
}
else if ( o . methods [ i ] . ReturnType = = PrimitiveTypeWrapper . CHAR )
{
getCharValueMethod . EmitCall ( ilgen ) ;
}
else if ( o . methods [ i ] . ReturnType = = PrimitiveTypeWrapper . SHORT )
{
getShortValueMethod . EmitCall ( ilgen ) ;
}
else if ( o . methods [ i ] . ReturnType = = PrimitiveTypeWrapper . INT )
{
getIntValueMethod . EmitCall ( ilgen ) ;
}
else if ( o . methods [ i ] . ReturnType = = PrimitiveTypeWrapper . FLOAT )
{
getFloatValueMethod . EmitCall ( ilgen ) ;
}
else if ( o . methods [ i ] . ReturnType = = PrimitiveTypeWrapper . LONG )
{
getLongValueMethod . EmitCall ( ilgen ) ;
}
else if ( o . methods [ i ] . ReturnType = = PrimitiveTypeWrapper . DOUBLE )
{
getDoubleValueMethod . EmitCall ( ilgen ) ;
}
else if ( o . methods [ i ] . ReturnType = = PrimitiveTypeWrapper . VOID )
{
// TODO what to do here?
ilgen . Emit ( OpCodes . Pop ) ;
ilgen . Emit ( OpCodes . Pop ) ;
}
else
{
throw new InvalidOperationException ( ) ;
}
}
else
{
getValueMethod . EmitCall ( ilgen ) ;
o . methods [ i ] . ReturnType . EmitCheckcast ( null , ilgen ) ;
}
ilgen . Emit ( OpCodes . Ret ) ;
}
}
attributeTypeBuilder . CreateType ( ) ;
2004-12-21 13:26:51 +03:00
}
2005-11-01 17:01:42 +03:00
internal override void Apply ( TypeBuilder tb , object annotation )
2004-12-21 13:26:51 +03:00
{
2006-04-05 15:04:43 +04:00
if ( annotationTypeBuilder ! = null )
{
tb . SetCustomAttribute ( new CustomAttributeBuilder ( defineConstructor , new object [ ] { annotation } ) ) ;
}
2004-12-21 13:26:51 +03:00
}
2002-12-18 19:00:25 +03:00
}
2006-04-14 18:11:39 +04:00
#endif // STATIC_COMPILER
2003-12-24 14:51:41 +03:00
2005-06-01 13:49:30 +04:00
internal class JniProxyBuilder
2004-09-05 13:37:58 +04:00
{
2005-06-01 13:49:30 +04:00
private static ModuleBuilder mod ;
private static int count ;
2004-09-05 13:37:58 +04:00
2005-06-01 13:49:30 +04:00
static JniProxyBuilder ( )
2003-08-13 19:00:41 +04:00
{
2005-08-08 16:41:46 +04:00
AssemblyName name = new AssemblyName ( ) ;
name . Name = "jniproxy" ;
2006-02-22 17:44:07 +03:00
AssemblyBuilder ab = AppDomain . CurrentDomain . DefineDynamicAssembly ( name , DynamicClassLoader . IsSaveDebugImage ? AssemblyBuilderAccess . RunAndSave : AssemblyBuilderAccess . Run ) ;
DynamicClassLoader . RegisterForSaveDebug ( ab ) ;
2005-08-08 16:41:46 +04:00
mod = ab . DefineDynamicModule ( "jniproxy.dll" , "jniproxy.dll" ) ;
2005-12-07 12:06:32 +03:00
AttributeHelper . SetJavaModule ( mod ) ;
2003-08-13 19:00:41 +04:00
}
2003-05-30 16:08:59 +04:00
2005-06-01 13:49:30 +04:00
internal static void Generate ( ILGenerator ilGenerator , DynamicTypeWrapper wrapper , MethodWrapper mw , TypeBuilder typeBuilder , ClassFile classFile , ClassFile . Method m , TypeWrapper [ ] args )
2004-09-05 13:37:58 +04:00
{
2005-08-08 16:41:46 +04:00
TypeBuilder tb = mod . DefineType ( "__<jni>" + ( count + + ) , TypeAttributes . Public | TypeAttributes . Class ) ;
2005-06-01 13:49:30 +04:00
int instance = m . IsStatic ? 0 : 1 ;
Type [ ] argTypes = new Type [ args . Length + instance + 1 ] ;
if ( instance ! = 0 )
{
2005-08-08 16:41:46 +04:00
argTypes [ 0 ] = typeof ( object ) ;
2005-06-01 13:49:30 +04:00
}
for ( int i = 0 ; i < args . Length ; i + + )
{
2005-08-08 16:41:46 +04:00
// NOTE we take a shortcut here by assuming that all "special" types (i.e. ghost or value types)
// are public and so we can get away with replacing all other types with object.
argTypes [ i + instance ] = ( args [ i ] . IsPrimitive | | args [ i ] . IsGhost | | args [ i ] . IsNonPrimitiveValueType ) ? args [ i ] . TypeAsSignatureType : typeof ( object ) ;
2005-06-01 13:49:30 +04:00
}
argTypes [ argTypes . Length - 1 ] = typeof ( RuntimeMethodHandle ) ;
2005-08-08 16:41:46 +04:00
Type retType = ( mw . ReturnType . IsPrimitive | | mw . ReturnType . IsGhost | | mw . ReturnType . IsNonPrimitiveValueType ) ? mw . ReturnType . TypeAsSignatureType : typeof ( object ) ;
MethodBuilder mb = tb . DefineMethod ( "method" , MethodAttributes . Public | MethodAttributes . Static , retType , argTypes ) ;
AttributeHelper . HideFromJava ( mb ) ;
2005-06-01 13:49:30 +04:00
JniBuilder . Generate ( mb . GetILGenerator ( ) , wrapper , mw , tb , classFile , m , args , true ) ;
2005-08-08 16:41:46 +04:00
tb . CreateType ( ) ;
2005-06-01 13:49:30 +04:00
for ( int i = 0 ; i < argTypes . Length - 1 ; i + + )
{
ilGenerator . Emit ( OpCodes . Ldarg , ( short ) i ) ;
}
2004-09-05 13:37:58 +04:00
ilGenerator . Emit ( OpCodes . Ldtoken , ( MethodInfo ) mw . GetMethod ( ) ) ;
2005-06-01 13:49:30 +04:00
ilGenerator . Emit ( OpCodes . Call , mb ) ;
2005-08-08 16:41:46 +04:00
if ( ! mw . ReturnType . IsPrimitive & & ! mw . ReturnType . IsGhost & & ! mw . ReturnType . IsNonPrimitiveValueType )
{
ilGenerator . Emit ( OpCodes . Castclass , mw . ReturnType . TypeAsSignatureType ) ;
}
2005-06-01 13:49:30 +04:00
ilGenerator . Emit ( OpCodes . Ret ) ;
}
}
private class JniBuilder
{
2006-04-11 18:59:43 +04:00
#if STATIC_COMPILER
private static readonly Type localRefStructType = StaticCompiler . GetType ( "IKVM.Runtime.JNI.Frame" ) ;
#else
private static readonly Type localRefStructType = typeof ( IKVM . Runtime . JNI . Frame ) ;
#endif
2005-06-01 13:49:30 +04:00
private static readonly MethodInfo jniFuncPtrMethod = localRefStructType . GetMethod ( "GetFuncPtr" ) ;
private static readonly MethodInfo enterLocalRefStruct = localRefStructType . GetMethod ( "Enter" ) ;
private static readonly MethodInfo leaveLocalRefStruct = localRefStructType . GetMethod ( "Leave" ) ;
private static readonly MethodInfo makeLocalRef = localRefStructType . GetMethod ( "MakeLocalRef" ) ;
private static readonly MethodInfo unwrapLocalRef = localRefStructType . GetMethod ( "UnwrapLocalRef" ) ;
private static readonly MethodInfo writeLine = typeof ( Console ) . GetMethod ( "WriteLine" , new Type [ ] { typeof ( object ) } , null ) ;
private static readonly MethodInfo monitorEnter = typeof ( System . Threading . Monitor ) . GetMethod ( "Enter" , new Type [ ] { typeof ( object ) } ) ;
private static readonly MethodInfo monitorExit = typeof ( System . Threading . Monitor ) . GetMethod ( "Exit" , new Type [ ] { typeof ( object ) } ) ;
internal static void Generate ( ILGenerator ilGenerator , DynamicTypeWrapper wrapper , MethodWrapper mw , TypeBuilder typeBuilder , ClassFile classFile , ClassFile . Method m , TypeWrapper [ ] args , bool thruProxy )
{
LocalBuilder syncObject = null ;
FieldInfo classObjectField ;
if ( thruProxy )
{
2005-07-07 18:03:21 +04:00
classObjectField = typeBuilder . DefineField ( "__<classObject>" , typeof ( object ) , FieldAttributes . Static | FieldAttributes . Private | FieldAttributes . SpecialName ) ;
2005-06-01 13:49:30 +04:00
}
else
{
classObjectField = wrapper . ClassObjectField ;
}
if ( m . IsSynchronized & & m . IsStatic )
{
ilGenerator . Emit ( OpCodes . Ldsfld , classObjectField ) ;
Label label = ilGenerator . DefineLabel ( ) ;
ilGenerator . Emit ( OpCodes . Brtrue_S , label ) ;
ilGenerator . Emit ( OpCodes . Ldtoken , wrapper . TypeAsTBD ) ;
2006-04-11 16:05:24 +04:00
ilGenerator . Emit ( OpCodes . Call , ByteCodeHelperMethods . GetClassFromTypeHandle ) ;
2005-06-01 13:49:30 +04:00
ilGenerator . Emit ( OpCodes . Stsfld , classObjectField ) ;
ilGenerator . MarkLabel ( label ) ;
ilGenerator . Emit ( OpCodes . Ldsfld , classObjectField ) ;
ilGenerator . Emit ( OpCodes . Dup ) ;
syncObject = ilGenerator . DeclareLocal ( typeof ( object ) ) ;
ilGenerator . Emit ( OpCodes . Stloc , syncObject ) ;
ilGenerator . Emit ( OpCodes . Call , monitorEnter ) ;
ilGenerator . BeginExceptionBlock ( ) ;
}
string sig = m . Signature . Replace ( '.' , '/' ) ;
2006-04-10 13:09:09 +04:00
// TODO use/unify JNI.METHOD_PTR_FIELD_PREFIX
FieldBuilder methodPtr = typeBuilder . DefineField ( "__<jniptr>" + m . Name + sig , typeof ( IntPtr ) , FieldAttributes . Static | FieldAttributes . PrivateScope ) ;
2005-06-01 13:49:30 +04:00
LocalBuilder localRefStruct = ilGenerator . DeclareLocal ( localRefStructType ) ;
2003-05-30 16:08:59 +04:00
ilGenerator . Emit ( OpCodes . Ldloca , localRefStruct ) ;
2005-06-01 13:49:30 +04:00
ilGenerator . Emit ( OpCodes . Initobj , localRefStructType ) ;
ilGenerator . Emit ( OpCodes . Ldsfld , methodPtr ) ;
Label oklabel = ilGenerator . DefineLabel ( ) ;
ilGenerator . Emit ( OpCodes . Brtrue , oklabel ) ;
if ( thruProxy )
{
ilGenerator . Emit ( OpCodes . Ldarg_S , ( byte ) ( args . Length + ( mw . IsStatic ? 0 : 1 ) ) ) ;
}
else
{
ilGenerator . Emit ( OpCodes . Ldtoken , ( MethodInfo ) mw . GetMethod ( ) ) ;
}
ilGenerator . Emit ( OpCodes . Ldstr , classFile . Name . Replace ( '.' , '/' ) ) ;
ilGenerator . Emit ( OpCodes . Ldstr , m . Name ) ;
ilGenerator . Emit ( OpCodes . Ldstr , sig ) ;
ilGenerator . Emit ( OpCodes . Call , jniFuncPtrMethod ) ;
ilGenerator . Emit ( OpCodes . Stsfld , methodPtr ) ;
ilGenerator . MarkLabel ( oklabel ) ;
2003-05-30 16:08:59 +04:00
ilGenerator . Emit ( OpCodes . Ldloca , localRefStruct ) ;
2005-06-01 13:49:30 +04:00
if ( thruProxy )
{
ilGenerator . Emit ( OpCodes . Ldarg_S , ( byte ) ( args . Length + ( mw . IsStatic ? 0 : 1 ) ) ) ;
}
else
{
ilGenerator . Emit ( OpCodes . Ldtoken , ( MethodInfo ) mw . GetMethod ( ) ) ;
}
ilGenerator . Emit ( OpCodes . Call , enterLocalRefStruct ) ;
LocalBuilder jnienv = ilGenerator . DeclareLocal ( typeof ( IntPtr ) ) ;
ilGenerator . Emit ( OpCodes . Stloc , jnienv ) ;
2005-06-03 10:41:48 +04:00
ilGenerator . BeginExceptionBlock ( ) ;
2005-06-01 13:49:30 +04:00
TypeWrapper retTypeWrapper = mw . ReturnType ;
if ( ! retTypeWrapper . IsUnloadable & & ! retTypeWrapper . IsPrimitive )
{
// this one is for use after we return from "calli"
ilGenerator . Emit ( OpCodes . Ldloca , localRefStruct ) ;
}
ilGenerator . Emit ( OpCodes . Ldloc , jnienv ) ;
Type [ ] modargs = new Type [ args . Length + 2 ] ;
modargs [ 0 ] = typeof ( IntPtr ) ;
modargs [ 1 ] = typeof ( IntPtr ) ;
for ( int i = 0 ; i < args . Length ; i + + )
{
modargs [ i + 2 ] = args [ i ] . TypeAsSignatureType ;
}
int add = 0 ;
if ( ! m . IsStatic )
{
ilGenerator . Emit ( OpCodes . Ldloca , localRefStruct ) ;
ilGenerator . Emit ( OpCodes . Ldarg_0 ) ;
ilGenerator . Emit ( OpCodes . Call , makeLocalRef ) ;
add = 1 ;
}
else
{
ilGenerator . Emit ( OpCodes . Ldloca , localRefStruct ) ;
2004-09-17 13:32:06 +04:00
2005-06-01 13:49:30 +04:00
ilGenerator . Emit ( OpCodes . Ldsfld , classObjectField ) ;
Label label = ilGenerator . DefineLabel ( ) ;
ilGenerator . Emit ( OpCodes . Brtrue_S , label ) ;
ilGenerator . Emit ( OpCodes . Ldtoken , wrapper . TypeAsTBD ) ;
2006-04-11 16:05:24 +04:00
ilGenerator . Emit ( OpCodes . Call , ByteCodeHelperMethods . GetClassFromTypeHandle ) ;
2005-06-01 13:49:30 +04:00
ilGenerator . Emit ( OpCodes . Stsfld , classObjectField ) ;
ilGenerator . MarkLabel ( label ) ;
ilGenerator . Emit ( OpCodes . Ldsfld , classObjectField ) ;
2004-09-17 13:32:06 +04:00
2005-06-01 13:49:30 +04:00
ilGenerator . Emit ( OpCodes . Call , makeLocalRef ) ;
}
for ( int j = 0 ; j < args . Length ; j + + )
2003-05-30 16:08:59 +04:00
{
2005-06-01 13:49:30 +04:00
if ( args [ j ] . IsUnloadable | | ! args [ j ] . IsPrimitive )
2005-02-02 18:11:26 +03:00
{
2005-06-01 13:49:30 +04:00
ilGenerator . Emit ( OpCodes . Ldloca , localRefStruct ) ;
if ( ! args [ j ] . IsUnloadable & & args [ j ] . IsNonPrimitiveValueType )
{
ilGenerator . Emit ( OpCodes . Ldarg_S , ( byte ) ( j + add ) ) ;
args [ j ] . EmitBox ( ilGenerator ) ;
}
else if ( ! args [ j ] . IsUnloadable & & args [ j ] . IsGhost )
{
ilGenerator . Emit ( OpCodes . Ldarga_S , ( byte ) ( j + add ) ) ;
ilGenerator . Emit ( OpCodes . Ldfld , args [ j ] . GhostRefField ) ;
}
else
{
ilGenerator . Emit ( OpCodes . Ldarg_S , ( byte ) ( j + add ) ) ;
}
ilGenerator . Emit ( OpCodes . Call , makeLocalRef ) ;
modargs [ j + 2 ] = typeof ( IntPtr ) ;
2005-02-02 18:11:26 +03:00
}
else
{
ilGenerator . Emit ( OpCodes . Ldarg_S , ( byte ) ( j + add ) ) ;
}
2005-06-01 13:49:30 +04:00
}
ilGenerator . Emit ( OpCodes . Ldsfld , methodPtr ) ;
Type realRetType ;
if ( retTypeWrapper = = PrimitiveTypeWrapper . BOOLEAN )
{
realRetType = typeof ( byte ) ;
}
else if ( retTypeWrapper . IsPrimitive )
{
realRetType = retTypeWrapper . TypeAsSignatureType ;
2003-05-30 16:08:59 +04:00
}
else
{
2005-06-01 13:49:30 +04:00
realRetType = typeof ( IntPtr ) ;
2003-05-30 16:08:59 +04:00
}
2005-06-01 13:49:30 +04:00
ilGenerator . EmitCalli ( OpCodes . Calli , System . Runtime . InteropServices . CallingConvention . StdCall , realRetType , modargs ) ;
LocalBuilder retValue = null ;
if ( retTypeWrapper ! = PrimitiveTypeWrapper . VOID )
2003-05-30 16:08:59 +04:00
{
2005-06-01 13:49:30 +04:00
if ( ! retTypeWrapper . IsUnloadable & & ! retTypeWrapper . IsPrimitive )
2005-02-02 18:11:26 +03:00
{
2005-06-01 13:49:30 +04:00
ilGenerator . Emit ( OpCodes . Call , unwrapLocalRef ) ;
if ( retTypeWrapper . IsNonPrimitiveValueType )
{
retTypeWrapper . EmitUnbox ( ilGenerator ) ;
}
else if ( retTypeWrapper . IsGhost )
{
LocalBuilder ghost = ilGenerator . DeclareLocal ( retTypeWrapper . TypeAsSignatureType ) ;
LocalBuilder obj = ilGenerator . DeclareLocal ( typeof ( object ) ) ;
ilGenerator . Emit ( OpCodes . Stloc , obj ) ;
ilGenerator . Emit ( OpCodes . Ldloca , ghost ) ;
ilGenerator . Emit ( OpCodes . Ldloc , obj ) ;
ilGenerator . Emit ( OpCodes . Stfld , retTypeWrapper . GhostRefField ) ;
ilGenerator . Emit ( OpCodes . Ldloc , ghost ) ;
}
else
{
ilGenerator . Emit ( OpCodes . Castclass , retTypeWrapper . TypeAsTBD ) ;
}
2003-08-01 16:12:08 +04:00
}
2005-06-01 13:49:30 +04:00
retValue = ilGenerator . DeclareLocal ( retTypeWrapper . TypeAsSignatureType ) ;
ilGenerator . Emit ( OpCodes . Stloc , retValue ) ;
2003-05-30 16:08:59 +04:00
}
2005-06-01 13:49:30 +04:00
ilGenerator . BeginCatchBlock ( typeof ( object ) ) ;
ilGenerator . EmitWriteLine ( "*** exception in native code ***" ) ;
ilGenerator . Emit ( OpCodes . Call , writeLine ) ;
ilGenerator . Emit ( OpCodes . Rethrow ) ;
2004-09-27 14:17:34 +04:00
ilGenerator . BeginFinallyBlock ( ) ;
2005-06-01 13:49:30 +04:00
ilGenerator . Emit ( OpCodes . Ldloca , localRefStruct ) ;
ilGenerator . Emit ( OpCodes . Call , leaveLocalRefStruct ) ;
2004-09-27 14:17:34 +04:00
ilGenerator . EndExceptionBlock ( ) ;
2005-06-01 13:49:30 +04:00
if ( m . IsSynchronized & & m . IsStatic )
{
ilGenerator . BeginFinallyBlock ( ) ;
ilGenerator . Emit ( OpCodes . Ldloc , syncObject ) ;
ilGenerator . Emit ( OpCodes . Call , monitorExit ) ;
ilGenerator . EndExceptionBlock ( ) ;
}
if ( retTypeWrapper ! = PrimitiveTypeWrapper . VOID )
{
ilGenerator . Emit ( OpCodes . Ldloc , retValue ) ;
}
ilGenerator . Emit ( OpCodes . Ret ) ;
2004-09-27 14:17:34 +04:00
}
2003-05-30 16:08:59 +04:00
}
2002-12-18 19:00:25 +03:00
2005-06-01 13:49:30 +04:00
internal override TypeWrapper [ ] InnerClasses
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
throw new InvalidOperationException ( "InnerClasses is only available for finished types" ) ;
}
2002-12-18 19:00:25 +03:00
}
2005-06-01 13:49:30 +04:00
internal override TypeWrapper DeclaringTypeWrapper
2003-02-18 12:30:34 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
throw new InvalidOperationException ( "DeclaringTypeWrapper is only available for finished types" ) ;
}
2003-02-18 12:30:34 +03:00
}
2005-06-01 13:49:30 +04:00
internal override Modifiers ReflectiveModifiers
2003-02-18 12:30:34 +03:00
{
2005-06-01 13:49:30 +04:00
get
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
ClassFile . InnerClass [ ] innerclasses = classFile . InnerClasses ;
if ( innerclasses ! = null )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
for ( int i = 0 ; i < innerclasses . Length ; i + + )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
if ( innerclasses [ i ] . innerClass ! = 0 )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
if ( classFile . GetConstantPoolClass ( innerclasses [ i ] . innerClass ) = = wrapper . Name )
{
return innerclasses [ i ] . accessFlags ;
}
2004-08-17 13:05:21 +04:00
}
}
}
2005-06-01 13:49:30 +04:00
return classFile . Modifiers ;
2004-08-17 13:05:21 +04:00
}
2003-02-18 12:30:34 +03:00
}
2005-06-01 13:49:30 +04:00
private void UpdateClashTable ( )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
lock ( this )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
if ( memberclashtable = = null )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
memberclashtable = new Hashtable ( ) ;
for ( int i = 0 ; i < methods . Length ; i + + )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
// TODO at the moment we don't support constructor signature clash resolving, so we better
// not put them in the clash table
if ( methods [ i ] . IsLinked & & methods [ i ] . Name ! = "<init>" )
{
string key = GenerateClashKey ( "method" , methods [ i ] . RealName , methods [ i ] . ReturnTypeForDefineMethod , methods [ i ] . GetParametersForDefineMethod ( ) ) ;
memberclashtable . Add ( key , key ) ;
}
2004-08-17 13:05:21 +04:00
}
}
}
}
2005-06-01 13:49:30 +04:00
private static string GenerateClashKey ( string type , string name , Type retOrFieldType , Type [ ] args )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
System . Text . StringBuilder sb = new System . Text . StringBuilder ( type ) ;
sb . Append ( ':' ) . Append ( name ) . Append ( ':' ) . Append ( retOrFieldType . FullName ) ;
if ( args ! = null )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
foreach ( Type t in args )
{
sb . Append ( ':' ) . Append ( t . FullName ) ;
}
2004-08-17 13:05:21 +04:00
}
2005-06-01 13:49:30 +04:00
return sb . ToString ( ) ;
2004-08-17 13:05:21 +04:00
}
2005-06-01 13:49:30 +04:00
private ConstructorBuilder DefineClassInitializer ( )
2002-12-29 19:27:00 +03:00
{
2005-06-01 13:49:30 +04:00
if ( typeBuilder . IsInterface )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
// LAMESPEC the ECMA spec says (part. I, sect. 8.5.3.2) that all interface members must be public, so we make
// the class constructor public
return typeBuilder . DefineConstructor ( MethodAttributes . Static | MethodAttributes . Public , CallingConventions . Standard , Type . EmptyTypes ) ;
2004-08-17 13:05:21 +04:00
}
2005-06-01 13:49:30 +04:00
// NOTE we don't need to record the modifiers here, because they aren't visible from Java reflection
return typeBuilder . DefineTypeInitializer ( ) ;
2004-08-17 13:05:21 +04:00
}
2005-06-01 13:49:30 +04:00
// this finds the method that md is going to be overriding
private MethodWrapper FindBaseMethod ( string name , string sig , out bool explicitOverride )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
Debug . Assert ( ! classFile . IsInterface ) ;
Debug . Assert ( name ! = "<init>" ) ;
2004-08-17 13:05:21 +04:00
2005-06-01 13:49:30 +04:00
explicitOverride = false ;
TypeWrapper tw = wrapper . BaseTypeWrapper ;
while ( tw ! = null )
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
MethodWrapper baseMethod = tw . GetMethodWrapper ( name , sig , true ) ;
if ( baseMethod = = null )
2003-05-30 16:08:59 +04:00
{
2005-06-01 13:49:30 +04:00
return null ;
2003-05-30 16:08:59 +04:00
}
2005-06-01 13:49:30 +04:00
// here are the complex rules for determining whether this method overrides the method we found
// RULE 1: final methods may not be overridden
2006-04-05 12:18:58 +04:00
// (note that we intentionally not check IsStatic here!)
if ( baseMethod . IsFinal
& & ! baseMethod . IsPrivate
& & ( baseMethod . IsPublic | | baseMethod . IsProtected | | baseMethod . DeclaringType . IsInSamePackageAs ( wrapper ) ) )
2003-05-30 16:08:59 +04:00
{
2005-06-28 11:12:28 +04:00
throw new VerifyError ( "final method " + baseMethod . Name + baseMethod . Signature + " in " + baseMethod . DeclaringType . Name + " is overriden in " + wrapper . Name ) ;
2003-05-30 16:08:59 +04:00
}
2006-04-05 12:18:58 +04:00
// RULE 1a: static methods are ignored (other than the RULE 1 check)
if ( baseMethod . IsStatic )
{
}
2005-06-01 13:49:30 +04:00
// RULE 2: public & protected methods can be overridden (package methods are handled by RULE 4)
// (by public, protected & *package* methods [even if they are in a different package])
2006-04-05 12:18:58 +04:00
else if ( baseMethod . IsPublic | | baseMethod . IsProtected )
2005-05-31 12:57:24 +04:00
{
2005-06-01 13:49:30 +04:00
// if we already encountered a package method, we cannot override the base method of
// that package method
if ( explicitOverride )
{
explicitOverride = false ;
return null ;
}
return baseMethod ;
2005-05-31 12:57:24 +04:00
}
2006-04-05 12:18:58 +04:00
// RULE 3: private and static methods are ignored
else if ( ! baseMethod . IsPrivate )
2005-05-31 12:57:24 +04:00
{
2005-06-01 13:49:30 +04:00
// RULE 4: package methods can only be overridden in the same package
2006-04-05 12:18:58 +04:00
if ( baseMethod . DeclaringType . IsInSamePackageAs ( wrapper )
| | ( baseMethod . IsInternal & & baseMethod . DeclaringType . Assembly = = wrapper . Assembly ) )
2005-06-01 13:49:30 +04:00
{
return baseMethod ;
}
// since we encountered a method with the same name/signature that we aren't overriding,
// we need to specify an explicit override
// NOTE we only do this if baseMethod isn't private, because if it is, Reflection.Emit
// will complain about the explicit MethodOverride (possibly a bug)
explicitOverride = true ;
2005-05-31 12:57:24 +04:00
}
2005-06-01 13:49:30 +04:00
tw = baseMethod . DeclaringType . BaseTypeWrapper ;
2005-05-31 12:57:24 +04:00
}
2005-06-01 13:49:30 +04:00
return null ;
}
internal string GenerateUniqueMethodName ( string basename , MethodWrapper mw )
{
string name = basename ;
string key = GenerateClashKey ( "method" , name , mw . ReturnTypeForDefineMethod , mw . GetParametersForDefineMethod ( ) ) ;
UpdateClashTable ( ) ;
lock ( memberclashtable . SyncRoot )
2003-05-30 16:08:59 +04:00
{
2005-06-01 13:49:30 +04:00
for ( int clashcount = 0 ; memberclashtable . ContainsKey ( key ) ; clashcount + + )
{
name = basename + "_" + clashcount ;
key = GenerateClashKey ( "method" , name , mw . ReturnTypeForDefineMethod , mw . GetParametersForDefineMethod ( ) ) ;
}
memberclashtable . Add ( key , key ) ;
2003-05-30 16:08:59 +04:00
}
2005-06-01 13:49:30 +04:00
return name ;
}
private MethodBase GenerateMethod ( int index , bool unloadableOverrideStub )
{
methods [ index ] . AssertLinked ( ) ;
Profiler . Enter ( "JavaTypeImpl.GenerateMethod" ) ;
try
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
if ( index > = classFile . Methods . Length )
2004-08-17 13:05:21 +04:00
{
2005-08-14 19:49:50 +04:00
if ( methods [ index ] . IsMirandaMethod )
2005-06-01 13:49:30 +04:00
{
2005-08-14 19:49:50 +04:00
// We're a Miranda method
Debug . Assert ( baseMethods [ index ] . DeclaringType . IsInterface ) ;
string name = GenerateUniqueMethodName ( methods [ index ] . Name , baseMethods [ index ] ) ;
2005-09-01 11:34:53 +04:00
MethodBuilder mb = typeBuilder . DefineMethod ( methods [ index ] . Name , MethodAttributes . HideBySig | MethodAttributes . NewSlot | MethodAttributes . Public | MethodAttributes . Virtual | MethodAttributes . Abstract | MethodAttributes . CheckAccessOnOverride , methods [ index ] . ReturnTypeForDefineMethod , methods [ index ] . GetParametersForDefineMethod ( ) ) ;
2005-08-14 19:49:50 +04:00
AttributeHelper . HideFromReflection ( mb ) ;
if ( unloadableOverrideStub | | name ! = methods [ index ] . Name )
{
// instead of creating an override stub, we created the Miranda method with the proper signature and
// decorate it with a NameSigAttribute that contains the real signature
AttributeHelper . SetNameSig ( mb , methods [ index ] . Name , methods [ index ] . Signature ) ;
}
// if we changed the name or if the interface method name is remapped, we need to add an explicit methodoverride.
if ( name ! = baseMethods [ index ] . RealName )
{
typeBuilder . DefineMethodOverride ( mb , ( MethodInfo ) baseMethods [ index ] . GetMethod ( ) ) ;
}
return mb ;
}
else if ( methods [ index ] . IsAccessStub )
{
MethodAttributes stubattribs = baseMethods [ index ] . IsPublic ? MethodAttributes . Public : MethodAttributes . FamORAssem ;
2005-09-01 11:34:53 +04:00
stubattribs | = MethodAttributes . HideBySig ;
2005-08-14 19:49:50 +04:00
if ( baseMethods [ index ] . IsStatic )
{
stubattribs | = MethodAttributes . Static ;
}
else
{
stubattribs | = MethodAttributes . CheckAccessOnOverride | MethodAttributes . Virtual ;
2005-10-02 00:22:45 +04:00
if ( baseMethods [ index ] . IsAbstract & & wrapper . IsAbstract )
2005-08-14 19:49:50 +04:00
{
stubattribs | = MethodAttributes . Abstract ;
}
if ( baseMethods [ index ] . IsFinal )
{
// NOTE final methods still need to be virtual, because a subclass may need this method to
// implement an interface method
stubattribs | = MethodAttributes . Final | MethodAttributes . NewSlot ;
}
}
MethodBuilder mb = typeBuilder . DefineMethod ( methods [ index ] . Name , stubattribs , methods [ index ] . ReturnTypeForDefineMethod , methods [ index ] . GetParametersForDefineMethod ( ) ) ;
AttributeHelper . HideFromReflection ( mb ) ;
if ( ! baseMethods [ index ] . IsAbstract )
{
ILGenerator ilgen = mb . GetILGenerator ( ) ;
int argc = methods [ index ] . GetParametersForDefineMethod ( ) . Length + ( methods [ index ] . IsStatic ? 0 : 1 ) ;
for ( int i = 0 ; i < argc ; i + + )
{
ilgen . Emit ( OpCodes . Ldarg_S , ( byte ) i ) ;
}
baseMethods [ index ] . EmitCall ( ilgen ) ;
ilgen . Emit ( OpCodes . Ret ) ;
}
2005-10-02 00:22:45 +04:00
else if ( ! wrapper . IsAbstract )
{
EmitHelper . Throw ( mb . GetILGenerator ( ) , "java.lang.AbstractMethodError" , wrapper . Name + "." + methods [ index ] . Name + methods [ index ] . Signature ) ;
}
2005-08-14 19:49:50 +04:00
return mb ;
2005-06-01 13:49:30 +04:00
}
2005-08-14 19:49:50 +04:00
else
2005-06-01 13:49:30 +04:00
{
2005-08-14 19:49:50 +04:00
throw new InvalidOperationException ( ) ;
2005-06-01 13:49:30 +04:00
}
2004-08-17 13:05:21 +04:00
}
2005-06-01 13:49:30 +04:00
ClassFile . Method m = classFile . Methods [ index ] ;
MethodBase method ;
bool setNameSig = methods [ index ] . ReturnType . IsUnloadable | | methods [ index ] . ReturnType . IsGhostArray ;
foreach ( TypeWrapper tw in methods [ index ] . GetParameters ( ) )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
setNameSig | = tw . IsUnloadable | | tw . IsGhostArray ;
}
bool setModifiers = false ;
2005-09-01 11:34:53 +04:00
MethodAttributes attribs = MethodAttributes . HideBySig ;
2005-06-01 13:49:30 +04:00
if ( m . IsNative )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
if ( wrapper . IsPInvokeMethod ( m ) )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
// this doesn't appear to be necessary, but we use the flag in Finish to know
// that we shouldn't emit a method body
attribs | = MethodAttributes . PinvokeImpl ;
2004-08-17 13:05:21 +04:00
}
else
{
setModifiers = true ;
}
}
2005-06-01 13:49:30 +04:00
if ( m . IsPrivate )
{
attribs | = MethodAttributes . Private ;
}
else if ( m . IsProtected )
{
attribs | = MethodAttributes . FamORAssem ;
}
2006-04-05 12:18:58 +04:00
else if ( m . IsPublic )
2005-06-01 13:49:30 +04:00
{
attribs | = MethodAttributes . Public ;
}
else
{
attribs | = MethodAttributes . Assembly ;
}
if ( m . Name = = "<init>" )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
if ( setNameSig )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
// TODO we might have to mangle the signature to make it unique
2004-08-17 13:05:21 +04:00
}
2005-06-01 13:49:30 +04:00
// strictfp is the only modifier that a constructor can have
if ( m . IsStrictfp )
2004-08-17 13:05:21 +04:00
{
setModifiers = true ;
}
2005-06-01 13:49:30 +04:00
method = typeBuilder . DefineConstructor ( attribs , CallingConventions . Standard , methods [ index ] . GetParametersForDefineMethod ( ) ) ;
( ( ConstructorBuilder ) method ) . SetImplementationFlags ( MethodImplAttributes . NoInlining ) ;
wrapper . AddParameterNames ( classFile , m , method ) ;
2004-08-17 13:05:21 +04:00
}
2005-06-01 13:49:30 +04:00
else if ( m . IsClassInitializer )
2003-05-30 16:08:59 +04:00
{
2005-06-01 13:49:30 +04:00
method = DefineClassInitializer ( ) ;
2003-05-30 16:08:59 +04:00
}
2005-06-01 13:49:30 +04:00
else
2003-05-30 16:08:59 +04:00
{
2005-06-01 13:49:30 +04:00
if ( m . IsAbstract )
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
// only if the classfile is abstract, we make the CLR method abstract, otherwise,
// we have to generate a method that throws an AbstractMethodError (because the JVM
// allows abstract methods in non-abstract classes)
if ( classFile . IsAbstract )
{
attribs | = MethodAttributes . Abstract ;
}
else
{
setModifiers = true ;
}
2002-12-18 19:00:25 +03:00
}
2005-06-01 13:49:30 +04:00
if ( m . IsFinal )
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
if ( ! m . IsStatic & & ! m . IsPrivate )
{
attribs | = MethodAttributes . Final ;
}
else
2002-12-18 19:00:25 +03:00
{
2003-05-30 16:08:59 +04:00
setModifiers = true ;
2002-12-18 19:00:25 +03:00
}
}
2005-06-01 13:49:30 +04:00
if ( m . IsStatic )
{
attribs | = MethodAttributes . Static ;
2005-09-08 21:44:35 +04:00
if ( m . IsSynchronized )
{
setModifiers = true ;
}
2005-06-01 13:49:30 +04:00
}
else if ( ! m . IsPrivate )
{
attribs | = MethodAttributes . Virtual | MethodAttributes . CheckAccessOnOverride ;
}
string name = m . Name ;
// if a method is virtual, we need to find the method it overrides (if any), for several reasons:
// - if we're overriding a method that has a different name (e.g. some of the virtual methods
// in System.Object [Equals <-> equals]) we need to add an explicit MethodOverride
// - if one of the base classes has a similar method that is private (or package) that we aren't
// overriding, we need to specify an explicit MethodOverride
MethodWrapper baseMce = baseMethods [ index ] ;
bool explicitOverride = methods [ index ] . IsExplicitOverride ;
if ( ( attribs & MethodAttributes . Virtual ) ! = 0 & & ! classFile . IsInterface )
2004-03-16 20:10:09 +03:00
{
2005-06-01 13:49:30 +04:00
// make sure the base method is already defined
Debug . Assert ( baseMce = = null | | baseMce . GetMethod ( ) ! = null ) ;
if ( baseMce = = null | | baseMce . DeclaringType . IsInterface )
2004-03-16 20:10:09 +03:00
{
2005-06-01 13:49:30 +04:00
// we need to set NewSlot here, to prevent accidentally overriding methods
// (for example, if a Java class has a method "boolean Equals(object)", we don't want that method
// to override System.Object.Equals)
2004-03-16 20:10:09 +03:00
attribs | = MethodAttributes . NewSlot ;
}
2005-06-01 13:49:30 +04:00
else
2004-03-16 20:10:09 +03:00
{
2005-06-01 13:49:30 +04:00
// if we have a method overriding a more accessible method (the JVM allows this), we need to make the
// method more accessible, because otherwise the CLR will complain that we're reducing access
MethodBase baseMethod = baseMce . GetMethod ( ) ;
if ( ( baseMethod . IsPublic & & ! m . IsPublic ) | |
2006-04-05 12:18:58 +04:00
( ( baseMethod . IsFamily | | baseMethod . IsFamilyOrAssembly ) & & ! m . IsPublic & & ! m . IsProtected ) | |
2005-06-01 13:49:30 +04:00
( ! m . IsPublic & & ! m . IsProtected & & ! baseMce . DeclaringType . IsInSamePackageAs ( wrapper ) ) )
{
attribs & = ~ MethodAttributes . MemberAccessMask ;
attribs | = baseMethod . IsPublic ? MethodAttributes . Public : MethodAttributes . FamORAssem ;
setModifiers = true ;
}
2004-03-16 20:10:09 +03:00
}
2005-06-01 13:49:30 +04:00
}
MethodBuilder mb = wrapper . DefineGhostMethod ( name , attribs , methods [ index ] ) ;
if ( mb = = null )
{
bool needFinalize = false ;
bool needDispatch = false ;
if ( baseMce ! = null & & m . Name = = "finalize" & & m . Signature = = "()V" )
2004-03-16 20:10:09 +03:00
{
2005-06-01 13:49:30 +04:00
if ( baseMce . RealName = = "Finalize" )
2004-12-02 11:43:05 +03:00
{
2005-06-01 13:49:30 +04:00
// We're overriding Finalize (that was renamed to finalize by DotNetTypeWrapper)
// in a non-Java base class.
attribs | = MethodAttributes . NewSlot ;
needFinalize = true ;
2004-12-02 11:43:05 +03:00
needDispatch = true ;
}
2005-06-01 13:49:30 +04:00
else if ( baseMce . DeclaringType = = CoreClasses . java . lang . Object . Wrapper )
2004-12-02 11:43:05 +03:00
{
2005-06-01 13:49:30 +04:00
// This type is the first type in the hierarchy to introduce a finalize method
// (other than the one in java.lang.Object obviously), so we need to override
// the real Finalize method and emit a dispatch call to our finalize method.
2004-12-02 11:43:05 +03:00
needFinalize = true ;
needDispatch = true ;
}
2005-06-01 13:49:30 +04:00
else if ( m . IsFinal )
{
// One of our base classes already has a finalize method, so we already are
// hooked into the real Finalize, but we need to override it again, to make it
// final (so that non-Java types cannot override it either).
needFinalize = true ;
needDispatch = false ;
// If the base class finalize was optimized away, we need a dispatch call after all.
Type baseFinalizeType = typeBuilder . BaseType . GetMethod ( "Finalize" , BindingFlags . NonPublic | BindingFlags . Public | BindingFlags . Instance , null , Type . EmptyTypes , null ) . DeclaringType ;
if ( baseFinalizeType = = typeof ( object ) )
{
needDispatch = true ;
}
}
else
{
// One of our base classes already has a finalize method, but it may have been an empty
// method so that the hookup to the real Finalize was optimized away, we need to check
// for that.
Type baseFinalizeType = typeBuilder . BaseType . GetMethod ( "Finalize" , BindingFlags . NonPublic | BindingFlags . Public | BindingFlags . Instance , null , Type . EmptyTypes , null ) . DeclaringType ;
if ( baseFinalizeType = = typeof ( object ) )
{
needFinalize = true ;
needDispatch = true ;
}
}
if ( needFinalize & &
! m . IsAbstract & & ! m . IsNative & &
( ! m . IsFinal | | classFile . IsFinal ) & &
m . Instructions . Length > 0 & &
m . Instructions [ 0 ] . NormalizedOpCode = = NormalizedByteCode . __return )
{
// we've got an empty finalize method, so we don't need to override the real finalizer
// (not having a finalizer makes a huge perf difference)
needFinalize = false ;
}
2004-12-02 11:43:05 +03:00
}
2005-06-01 13:49:30 +04:00
if ( setNameSig | | memberclashtable ! = null )
2004-03-16 20:10:09 +03:00
{
2005-08-05 12:40:54 +04:00
// TODO we really should make sure that the name we generate doesn't already exist in a
// base class (not in the Java method namespace, but in the CLR method namespace)
2005-06-01 13:49:30 +04:00
name = GenerateUniqueMethodName ( name , methods [ index ] ) ;
2004-03-16 20:10:09 +03:00
}
2005-08-05 12:40:54 +04:00
bool needMethodImpl = baseMce ! = null & & ( explicitOverride | | baseMce . RealName ! = name ) & & ! needFinalize ;
if ( unloadableOverrideStub | | needMethodImpl )
{
attribs | = MethodAttributes . NewSlot ;
}
2005-06-01 13:49:30 +04:00
mb = typeBuilder . DefineMethod ( name , attribs , methods [ index ] . ReturnTypeForDefineMethod , methods [ index ] . GetParametersForDefineMethod ( ) ) ;
if ( unloadableOverrideStub )
2004-03-16 20:10:09 +03:00
{
2005-06-01 13:49:30 +04:00
GenerateUnloadableOverrideStub ( baseMce , mb , methods [ index ] . ReturnTypeForDefineMethod , methods [ index ] . GetParametersForDefineMethod ( ) ) ;
2004-03-16 20:10:09 +03:00
}
2005-08-05 12:40:54 +04:00
else if ( needMethodImpl )
2004-03-16 20:10:09 +03:00
{
2005-06-01 13:49:30 +04:00
// assert that the method we're overriding is in fact virtual and not final!
Debug . Assert ( baseMce . GetMethod ( ) . IsVirtual & & ! baseMce . GetMethod ( ) . IsFinal ) ;
typeBuilder . DefineMethodOverride ( mb , ( MethodInfo ) baseMce . GetMethod ( ) ) ;
2004-03-16 20:10:09 +03:00
}
2005-06-01 13:49:30 +04:00
// if we're overriding java.lang.Object.finalize we need to emit a stub to override System.Object.Finalize,
// or if we're subclassing a non-Java class that has a Finalize method, we need a new Finalize override
if ( needFinalize )
{
MethodInfo baseFinalize = typeBuilder . BaseType . GetMethod ( "Finalize" , BindingFlags . NonPublic | BindingFlags . Public | BindingFlags . Instance , null , Type . EmptyTypes , null ) ;
2005-09-01 11:34:53 +04:00
MethodAttributes attr = MethodAttributes . HideBySig | MethodAttributes . Virtual ;
2005-06-01 13:49:30 +04:00
// make sure we don't reduce accessibility
attr | = baseFinalize . IsPublic ? MethodAttributes . Public : MethodAttributes . Family ;
if ( m . IsFinal )
{
attr | = MethodAttributes . Final ;
}
// TODO if the Java class also defines a Finalize() method, we need to name the stub differently
// (and make it effectively appear hidden by the class's Finalize method)
MethodBuilder finalize = typeBuilder . DefineMethod ( "Finalize" , attr , CallingConventions . Standard , typeof ( void ) , Type . EmptyTypes ) ;
AttributeHelper . HideFromJava ( finalize ) ;
ILGenerator ilgen = finalize . GetILGenerator ( ) ;
2006-04-11 16:05:24 +04:00
ilgen . Emit ( OpCodes . Call , ByteCodeHelperMethods . SkipFinalizer ) ;
2005-06-01 13:49:30 +04:00
Label skip = ilgen . DefineLabel ( ) ;
ilgen . Emit ( OpCodes . Brtrue_S , skip ) ;
if ( needDispatch )
{
ilgen . BeginExceptionBlock ( ) ;
ilgen . Emit ( OpCodes . Ldarg_0 ) ;
ilgen . Emit ( OpCodes . Callvirt , mb ) ;
ilgen . BeginCatchBlock ( typeof ( object ) ) ;
ilgen . EndExceptionBlock ( ) ;
}
else
{
ilgen . Emit ( OpCodes . Ldarg_0 ) ;
ilgen . Emit ( OpCodes . Call , baseFinalize ) ;
}
ilgen . MarkLabel ( skip ) ;
ilgen . Emit ( OpCodes . Ret ) ;
}
2006-04-10 13:09:09 +04:00
#if STATIC_COMPILER
if ( classFile . Methods [ index ] . AnnotationDefault ! = null )
2005-11-01 17:01:42 +03:00
{
2006-04-11 18:59:43 +04:00
CustomAttributeBuilder cab = new CustomAttributeBuilder ( StaticCompiler . GetType ( "IKVM.Attributes.AnnotationDefaultAttribute" ) . GetConstructor ( new Type [ ] { typeof ( object ) } ) , new object [ ] { classFile . Methods [ index ] . AnnotationDefault } ) ;
2005-11-01 17:01:42 +03:00
mb . SetCustomAttribute ( cab ) ;
}
2006-04-10 13:09:09 +04:00
#endif
2005-06-01 13:49:30 +04:00
}
wrapper . AddParameterNames ( classFile , m , mb ) ;
method = mb ;
2003-07-31 16:49:29 +04:00
}
2005-06-01 13:49:30 +04:00
string [ ] exceptions = m . ExceptionsAttribute ;
methods [ index ] . SetDeclaredExceptions ( exceptions ) ;
2006-02-22 17:44:07 +03:00
if ( JVM . IsStaticCompiler | | DynamicClassLoader . IsSaveDebugImage )
2005-05-24 19:18:27 +04:00
{
2005-06-01 13:49:30 +04:00
AttributeHelper . SetThrowsAttribute ( method , exceptions ) ;
2006-04-05 12:18:58 +04:00
if ( setModifiers | | m . IsInternal | | ( m . Modifiers & ( Modifiers . Synthetic | Modifiers . Bridge ) ) ! = 0 )
2005-10-01 15:16:11 +04:00
{
if ( method is ConstructorBuilder )
{
2006-04-05 12:18:58 +04:00
AttributeHelper . SetModifiers ( ( ConstructorBuilder ) method , m . Modifiers , m . IsInternal ) ;
2005-10-01 15:16:11 +04:00
}
else
{
2006-04-05 12:18:58 +04:00
AttributeHelper . SetModifiers ( ( MethodBuilder ) method , m . Modifiers , m . IsInternal ) ;
2005-10-01 15:16:11 +04:00
}
}
2005-06-01 13:49:30 +04:00
if ( m . DeprecatedAttribute )
{
AttributeHelper . SetDeprecatedAttribute ( method ) ;
}
if ( setNameSig )
{
AttributeHelper . SetNameSig ( method , m . Name , m . Signature ) ;
}
2005-10-01 15:16:11 +04:00
if ( m . GenericSignature ! = null )
{
AttributeHelper . SetSignatureAttribute ( method , m . GenericSignature ) ;
}
2003-04-26 16:13:02 +04:00
}
2005-06-01 13:49:30 +04:00
return method ;
2003-05-10 19:34:49 +04:00
}
2005-06-01 13:49:30 +04:00
finally
2003-11-17 15:01:50 +03:00
{
2005-06-01 13:49:30 +04:00
Profiler . Leave ( "JavaTypeImpl.GenerateMethod" ) ;
2003-11-17 15:01:50 +03:00
}
2002-12-18 19:00:25 +03:00
}
2005-06-01 13:49:30 +04:00
private void GenerateUnloadableOverrideStub ( MethodWrapper baseMethod , MethodInfo target , Type targetRet , Type [ ] targetArgs )
2005-05-27 16:44:06 +04:00
{
2005-06-01 13:49:30 +04:00
Type stubret = baseMethod . ReturnTypeForDefineMethod ;
Type [ ] stubargs = baseMethod . GetParametersForDefineMethod ( ) ;
string name = GenerateUniqueMethodName ( baseMethod . RealName + "/unloadablestub" , baseMethod ) ;
MethodBuilder overrideStub = typeBuilder . DefineMethod ( name , MethodAttributes . Private | MethodAttributes . Virtual | MethodAttributes . NewSlot | MethodAttributes . Final , stubret , stubargs ) ;
AttributeHelper . HideFromJava ( overrideStub ) ;
typeBuilder . DefineMethodOverride ( overrideStub , ( MethodInfo ) baseMethod . GetMethod ( ) ) ;
ILGenerator ilgen = overrideStub . GetILGenerator ( ) ;
ilgen . Emit ( OpCodes . Ldarg_0 ) ;
for ( int i = 0 ; i < targetArgs . Length ; i + + )
2005-05-27 16:44:06 +04:00
{
2005-06-01 13:49:30 +04:00
ilgen . Emit ( OpCodes . Ldarg_S , ( byte ) ( i + 1 ) ) ;
if ( targetArgs [ i ] ! = stubargs [ i ] )
{
ilgen . Emit ( OpCodes . Castclass , targetArgs [ i ] ) ;
}
2005-05-27 16:44:06 +04:00
}
2005-06-01 13:49:30 +04:00
ilgen . Emit ( OpCodes . Callvirt , target ) ;
if ( targetRet ! = stubret )
{
ilgen . Emit ( OpCodes . Castclass , stubret ) ;
}
ilgen . Emit ( OpCodes . Ret ) ;
2005-05-27 16:44:06 +04:00
}
2005-06-01 13:49:30 +04:00
private static bool CheckRequireOverrideStub ( MethodWrapper mw1 , MethodWrapper mw2 )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
// TODO this is too late to generate LinkageErrors so we need to figure this out earlier
if ( mw1 . ReturnType ! = mw2 . ReturnType & & ! ( mw1 . ReturnType . IsUnloadable & & mw2 . ReturnType . IsUnloadable ) )
2004-08-17 13:05:21 +04:00
{
return true ;
2003-06-18 12:48:00 +04:00
}
2005-06-01 13:49:30 +04:00
TypeWrapper [ ] args1 = mw1 . GetParameters ( ) ;
TypeWrapper [ ] args2 = mw2 . GetParameters ( ) ;
for ( int i = 0 ; i < args1 . Length ; i + + )
{
if ( args1 [ i ] ! = args2 [ i ] & & ! ( args1 [ i ] . IsUnloadable & & args2 [ i ] . IsUnloadable ) )
{
return true ;
}
}
return false ;
2003-06-18 12:48:00 +04:00
}
2005-06-01 13:49:30 +04:00
private void AddMethodOverride ( MethodWrapper method , MethodBuilder mb , TypeWrapper iface , string name , string sig , ref Hashtable hashtable , bool unloadableOnly )
2003-05-10 19:34:49 +04:00
{
2005-06-01 13:49:30 +04:00
if ( hashtable ! = null & & hashtable . ContainsKey ( iface ) )
2003-05-10 19:34:49 +04:00
{
2005-06-01 13:49:30 +04:00
return ;
2003-05-10 19:34:49 +04:00
}
2005-06-01 13:49:30 +04:00
MethodWrapper mw = iface . GetMethodWrapper ( name , sig , false ) ;
if ( mw ! = null )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
if ( hashtable = = null )
{
hashtable = new Hashtable ( ) ;
}
hashtable . Add ( iface , iface ) ;
if ( CheckRequireOverrideStub ( method , mw ) )
{
GenerateUnloadableOverrideStub ( mw , mb , method . ReturnTypeForDefineMethod , method . GetParametersForDefineMethod ( ) ) ;
}
else if ( ! unloadableOnly )
{
typeBuilder . DefineMethodOverride ( mb , ( MethodInfo ) mw . GetMethod ( ) ) ;
}
2004-08-17 13:05:21 +04:00
}
2005-06-01 13:49:30 +04:00
foreach ( TypeWrapper iface2 in iface . Interfaces )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
AddMethodOverride ( method , mb , iface2 , name , sig , ref hashtable , unloadableOnly ) ;
2004-08-17 13:05:21 +04:00
}
2003-05-10 19:34:49 +04:00
}
2005-06-01 13:49:30 +04:00
internal override Type Type
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
return typeBuilder ;
}
2002-12-18 19:00:25 +03:00
}
2005-10-01 15:16:11 +04:00
internal override string GetGenericSignature ( )
{
Debug . Fail ( "Unreachable code" ) ;
return null ;
}
internal override string [ ] GetEnclosingMethod ( )
{
Debug . Fail ( "Unreachable code" ) ;
return null ;
}
internal override string GetGenericMethodSignature ( int index )
{
Debug . Fail ( "Unreachable code" ) ;
return null ;
}
internal override string GetGenericFieldSignature ( int index )
{
Debug . Fail ( "Unreachable code" ) ;
return null ;
}
2005-11-01 17:01:42 +03:00
internal override object [ ] GetDeclaredAnnotations ( )
{
Debug . Fail ( "Unreachable code" ) ;
return null ;
}
internal override object GetMethodDefaultValue ( int index )
{
Debug . Fail ( "Unreachable code" ) ;
return null ;
}
2006-04-19 19:49:54 +04:00
internal override object [ ] GetMethodAnnotations ( int index )
{
Debug . Fail ( "Unreachable code" ) ;
return null ;
}
internal override object [ ] [ ] GetParameterAnnotations ( int index )
{
Debug . Fail ( "Unreachable code" ) ;
return null ;
}
internal override object [ ] GetFieldAnnotations ( int index )
{
Debug . Fail ( "Unreachable code" ) ;
return null ;
}
2005-11-01 17:01:42 +03:00
}
private sealed class Metadata
{
private string [ ] genericMetaData ;
private object [ ] [ ] annotations ;
private Metadata ( string [ ] genericMetaData , object [ ] [ ] annotations )
{
this . genericMetaData = genericMetaData ;
this . annotations = annotations ;
}
internal static Metadata Create ( ClassFile classFile )
{
if ( classFile . MajorVersion < 49 )
{
return null ;
}
string [ ] genericMetaData = null ;
object [ ] [ ] annotations = null ;
for ( int i = 0 ; i < classFile . Methods . Length ; i + + )
{
if ( classFile . Methods [ i ] . GenericSignature ! = null )
{
if ( genericMetaData = = null )
{
genericMetaData = new string [ classFile . Methods . Length + classFile . Fields . Length + 4 ] ;
}
genericMetaData [ i + 4 ] = classFile . Methods [ i ] . GenericSignature ;
}
if ( classFile . Methods [ i ] . Annotations ! = null )
{
if ( annotations = = null )
{
annotations = new object [ 5 ] [ ] ;
}
if ( annotations [ 1 ] = = null )
{
annotations [ 1 ] = new object [ classFile . Methods . Length ] ;
}
annotations [ 1 ] [ i ] = classFile . Methods [ i ] . Annotations ;
}
if ( classFile . Methods [ i ] . ParameterAnnotations ! = null )
{
if ( annotations = = null )
{
annotations = new object [ 5 ] [ ] ;
}
if ( annotations [ 2 ] = = null )
{
annotations [ 2 ] = new object [ classFile . Methods . Length ] ;
}
annotations [ 2 ] [ i ] = classFile . Methods [ i ] . ParameterAnnotations ;
}
if ( classFile . Methods [ i ] . AnnotationDefault ! = null )
{
if ( annotations = = null )
{
annotations = new object [ 5 ] [ ] ;
}
if ( annotations [ 3 ] = = null )
{
annotations [ 3 ] = new object [ classFile . Methods . Length ] ;
}
annotations [ 3 ] [ i ] = classFile . Methods [ i ] . AnnotationDefault ;
}
}
for ( int i = 0 ; i < classFile . Fields . Length ; i + + )
{
if ( classFile . Fields [ i ] . GenericSignature ! = null )
{
if ( genericMetaData = = null )
{
genericMetaData = new string [ classFile . Methods . Length + classFile . Fields . Length + 4 ] ;
}
genericMetaData [ i + 4 + classFile . Methods . Length ] = classFile . Fields [ i ] . GenericSignature ;
}
if ( classFile . Fields [ i ] . Annotations ! = null )
{
if ( annotations = = null )
{
annotations = new object [ 5 ] [ ] ;
}
if ( annotations [ 4 ] = = null )
{
annotations [ 4 ] = new object [ classFile . Fields . Length ] [ ] ;
}
annotations [ 4 ] [ i ] = classFile . Fields [ i ] . Annotations ;
}
}
if ( classFile . EnclosingMethod ! = null )
{
if ( genericMetaData = = null )
{
genericMetaData = new string [ 4 ] ;
}
genericMetaData [ 0 ] = classFile . EnclosingMethod [ 0 ] ;
genericMetaData [ 1 ] = classFile . EnclosingMethod [ 1 ] ;
genericMetaData [ 2 ] = classFile . EnclosingMethod [ 2 ] ;
}
if ( classFile . GenericSignature ! = null )
{
if ( genericMetaData = = null )
{
genericMetaData = new string [ 4 ] ;
}
genericMetaData [ 3 ] = classFile . GenericSignature ;
}
if ( classFile . Annotations ! = null )
{
if ( annotations = = null )
{
annotations = new object [ 5 ] [ ] ;
}
annotations [ 0 ] = classFile . Annotations ;
}
if ( genericMetaData ! = null | | annotations ! = null )
{
return new Metadata ( genericMetaData , annotations ) ;
}
return null ;
}
internal static string GetGenericSignature ( Metadata m )
{
if ( m ! = null & & m . genericMetaData ! = null )
{
return m . genericMetaData [ 3 ] ;
}
return null ;
}
internal static string [ ] GetEnclosingMethod ( Metadata m )
{
if ( m ! = null & & m . genericMetaData ! = null & & m . genericMetaData [ 0 ] ! = null )
{
return new string [ ] { m . genericMetaData [ 0 ] , m . genericMetaData [ 1 ] , m . genericMetaData [ 2 ] } ;
}
return null ;
}
internal static string GetGenericMethodSignature ( Metadata m , int index )
{
if ( m ! = null & & m . genericMetaData ! = null )
{
return m . genericMetaData [ index + 4 ] ;
}
return null ;
}
// note that the caller is responsible for computing the correct index (field index + method count)
internal static string GetGenericFieldSignature ( Metadata m , int index )
{
if ( m ! = null & & m . genericMetaData ! = null )
{
return m . genericMetaData [ index + 4 ] ;
}
return null ;
}
internal static object [ ] GetAnnotations ( Metadata m )
{
if ( m ! = null & & m . annotations ! = null )
{
return m . annotations [ 0 ] ;
}
return null ;
}
internal static object [ ] GetMethodAnnotations ( Metadata m , int index )
{
if ( m ! = null & & m . annotations ! = null & & m . annotations [ 1 ] ! = null )
{
return ( object [ ] ) m . annotations [ 1 ] [ index ] ;
}
return null ;
}
internal static object [ ] [ ] GetMethodParameterAnnotations ( Metadata m , int index )
{
if ( m ! = null & & m . annotations ! = null & & m . annotations [ 2 ] ! = null )
{
return ( object [ ] [ ] ) m . annotations [ 2 ] [ index ] ;
}
return null ;
}
internal static object GetMethodDefaultValue ( Metadata m , int index )
{
if ( m ! = null & & m . annotations ! = null & & m . annotations [ 3 ] ! = null )
{
return m . annotations [ 3 ] [ index ] ;
}
return null ;
}
// note that unlike GetGenericFieldSignature, the index is simply the field index
internal static object [ ] GetFieldAnnotations ( Metadata m , int index )
{
2006-04-19 19:49:54 +04:00
if ( m ! = null & & m . annotations ! = null & & m . annotations [ 4 ] ! = null )
2005-11-01 17:01:42 +03:00
{
return ( object [ ] ) m . annotations [ 4 ] [ index ] ;
}
return null ;
}
2002-12-18 19:00:25 +03:00
}
2004-12-21 13:26:51 +03:00
2005-06-01 13:49:30 +04:00
private class FinishedTypeImpl : DynamicImpl
2003-02-18 12:30:34 +03:00
{
2005-06-01 13:49:30 +04:00
private Type type ;
private TypeWrapper [ ] innerclasses ;
private TypeWrapper declaringTypeWrapper ;
private Modifiers reflectiveModifiers ;
2005-08-24 12:14:23 +04:00
private MethodInfo clinitMethod ;
2005-11-01 17:01:42 +03:00
private Metadata metadata ;
2005-06-01 13:49:30 +04:00
2005-11-01 17:01:42 +03:00
internal FinishedTypeImpl ( Type type , TypeWrapper [ ] innerclasses , TypeWrapper declaringTypeWrapper , Modifiers reflectiveModifiers , Metadata metadata )
2003-02-18 12:30:34 +03:00
{
2005-06-01 13:49:30 +04:00
this . type = type ;
this . innerclasses = innerclasses ;
this . declaringTypeWrapper = declaringTypeWrapper ;
this . reflectiveModifiers = reflectiveModifiers ;
2005-08-24 12:14:23 +04:00
this . clinitMethod = type . GetMethod ( "__<clinit>" , BindingFlags . Static | BindingFlags . Public | BindingFlags . NonPublic ) ;
2005-11-01 17:01:42 +03:00
this . metadata = metadata ;
2003-02-18 12:30:34 +03:00
}
2005-06-01 13:49:30 +04:00
internal override TypeWrapper [ ] InnerClasses
2003-02-18 12:30:34 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
// TODO compute the innerclasses lazily (and fix JavaTypeImpl to not always compute them)
return innerclasses ;
}
2003-02-18 12:30:34 +03:00
}
2002-12-18 19:00:25 +03:00
2005-06-01 13:49:30 +04:00
internal override TypeWrapper DeclaringTypeWrapper
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
// TODO compute lazily (and fix JavaTypeImpl to not always compute it)
return declaringTypeWrapper ;
}
2002-12-18 19:00:25 +03:00
}
2005-06-01 13:49:30 +04:00
internal override Modifiers ReflectiveModifiers
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
return reflectiveModifiers ;
}
2002-12-18 19:00:25 +03:00
}
2005-06-01 13:49:30 +04:00
internal override Type Type
{
get
{
return type ;
}
}
2004-08-17 13:05:21 +04:00
2005-08-24 12:14:23 +04:00
internal override void EmitRunClassConstructor ( CountingILGenerator ilgen )
{
if ( clinitMethod ! = null )
{
ilgen . Emit ( OpCodes . Call , clinitMethod ) ;
}
}
2005-08-05 12:40:54 +04:00
internal override DynamicImpl Finish ( )
2005-06-01 13:49:30 +04:00
{
return this ;
}
2004-08-17 13:05:21 +04:00
2005-06-01 13:49:30 +04:00
internal override MethodBase LinkMethod ( MethodWrapper mw )
{
// we should never be called, because all methods on a finished type are already linked
Debug . Assert ( false ) ;
return mw . GetMethod ( ) ;
}
2004-01-18 01:46:43 +03:00
2005-06-01 13:49:30 +04:00
internal override FieldInfo LinkField ( FieldWrapper fw )
2005-05-30 19:30:13 +04:00
{
2005-06-01 13:49:30 +04:00
// we should never be called, because all fields on a finished type are already linked
Debug . Assert ( false ) ;
return fw . GetField ( ) ;
2005-05-30 19:30:13 +04:00
}
2005-10-01 15:16:11 +04:00
internal override string GetGenericSignature ( )
{
2005-11-01 17:01:42 +03:00
return Metadata . GetGenericSignature ( metadata ) ;
2005-10-01 15:16:11 +04:00
}
internal override string [ ] GetEnclosingMethod ( )
{
2005-11-01 17:01:42 +03:00
return Metadata . GetEnclosingMethod ( metadata ) ;
2005-10-01 15:16:11 +04:00
}
internal override string GetGenericMethodSignature ( int index )
{
2005-11-01 17:01:42 +03:00
return Metadata . GetGenericMethodSignature ( metadata , index ) ;
2005-10-01 15:16:11 +04:00
}
// note that the caller is responsible for computing the correct index (field index + method count)
internal override string GetGenericFieldSignature ( int index )
{
2005-11-01 17:01:42 +03:00
return Metadata . GetGenericFieldSignature ( metadata , index ) ;
}
internal override object [ ] GetDeclaredAnnotations ( )
{
return Metadata . GetAnnotations ( metadata ) ;
}
internal override object GetMethodDefaultValue ( int index )
{
return Metadata . GetMethodDefaultValue ( metadata , index ) ;
2005-10-01 15:16:11 +04:00
}
2006-04-19 19:49:54 +04:00
internal override object [ ] GetMethodAnnotations ( int index )
{
return Metadata . GetMethodAnnotations ( metadata , index ) ;
}
internal override object [ ] [ ] GetParameterAnnotations ( int index )
{
return Metadata . GetMethodParameterAnnotations ( metadata , index ) ;
}
internal override object [ ] GetFieldAnnotations ( int index )
{
return Metadata . GetFieldAnnotations ( metadata , index ) ;
}
2005-06-01 13:49:30 +04:00
}
protected static ParameterBuilder [ ] AddParameterNames ( MethodBase mb , ClassFile . Method m , string [ ] parameterNames )
{
ClassFile . Method . LocalVariableTableEntry [ ] localVars = m . LocalVariableTableAttribute ;
if ( localVars ! = null )
2005-05-30 19:30:13 +04:00
{
2005-06-01 13:49:30 +04:00
int bias = 1 ;
if ( m . IsStatic )
{
bias = 0 ;
}
ParameterBuilder [ ] parameterBuilders = new ParameterBuilder [ m . ArgMap . Length - bias ] ;
for ( int i = bias ; i < m . ArgMap . Length ; i + + )
2005-05-30 19:30:13 +04:00
{
2005-06-01 13:49:30 +04:00
if ( m . ArgMap [ i ] ! = - 1 )
2005-05-30 19:30:13 +04:00
{
2005-06-01 13:49:30 +04:00
for ( int j = 0 ; j < localVars . Length ; j + + )
2005-05-30 19:30:13 +04:00
{
2005-06-01 13:49:30 +04:00
if ( localVars [ j ] . index = = i & & parameterBuilders [ i - bias ] = = null )
2005-05-30 19:30:13 +04:00
{
2005-06-01 13:49:30 +04:00
string name = localVars [ j ] . name ;
if ( parameterNames ! = null & & parameterNames [ i - bias ] ! = null )
{
name = parameterNames [ i - bias ] ;
}
ParameterBuilder pb ;
if ( mb is MethodBuilder )
{
pb = ( ( MethodBuilder ) mb ) . DefineParameter ( m . ArgMap [ i ] + 1 - bias , ParameterAttributes . None , name ) ;
}
else
{
pb = ( ( ConstructorBuilder ) mb ) . DefineParameter ( m . ArgMap [ i ] , ParameterAttributes . None , name ) ;
}
parameterBuilders [ i - bias ] = pb ;
break ;
2005-05-30 19:30:13 +04:00
}
}
}
}
2005-06-01 13:49:30 +04:00
return parameterBuilders ;
}
else
{
return AddParameterNames ( mb , m . Signature , parameterNames ) ;
2005-05-30 19:30:13 +04:00
}
2004-01-18 01:46:43 +03:00
}
2005-06-01 13:49:30 +04:00
protected static ParameterBuilder [ ] AddParameterNames ( MethodBase mb , string sig , string [ ] parameterNames )
2004-03-08 18:18:47 +03:00
{
2005-06-01 13:49:30 +04:00
ArrayList names = new ArrayList ( ) ;
for ( int i = 1 ; sig [ i ] ! = ')' ; i + + )
2005-05-30 19:30:13 +04:00
{
if ( sig [ i ] = = 'L' )
{
i + + ;
int end = sig . IndexOf ( ';' , i ) ;
2005-06-01 13:49:30 +04:00
names . Add ( GetParameterName ( sig . Substring ( i , end - i ) ) ) ;
2005-05-30 19:30:13 +04:00
i = end ;
}
2005-06-01 13:49:30 +04:00
else if ( sig [ i ] = = '[' )
{
while ( sig [ + + i ] = = '[' ) ;
if ( sig [ i ] = = 'L' )
{
i + + ;
int end = sig . IndexOf ( ';' , i ) ;
names . Add ( GetParameterName ( sig . Substring ( i , end - i ) ) + "arr" ) ;
i = end ;
}
else
{
switch ( sig [ i ] )
{
case 'B' :
case 'Z' :
names . Add ( "barr" ) ;
break ;
case 'C' :
names . Add ( "charr" ) ;
break ;
case 'S' :
names . Add ( "sarr" ) ;
break ;
case 'I' :
names . Add ( "iarr" ) ;
break ;
case 'J' :
names . Add ( "larr" ) ;
break ;
case 'F' :
names . Add ( "farr" ) ;
break ;
case 'D' :
names . Add ( "darr" ) ;
break ;
}
}
}
2005-05-30 19:30:13 +04:00
else
{
switch ( sig [ i ] )
{
case 'B' :
case 'Z' :
2005-06-01 13:49:30 +04:00
names . Add ( "b" ) ;
2005-05-30 19:30:13 +04:00
break ;
case 'C' :
2005-06-01 13:49:30 +04:00
names . Add ( "ch" ) ;
2005-05-30 19:30:13 +04:00
break ;
case 'S' :
2005-06-01 13:49:30 +04:00
names . Add ( "s" ) ;
2005-05-30 19:30:13 +04:00
break ;
case 'I' :
2005-06-01 13:49:30 +04:00
names . Add ( "i" ) ;
2005-05-30 19:30:13 +04:00
break ;
case 'J' :
2005-06-01 13:49:30 +04:00
names . Add ( "l" ) ;
2005-05-30 19:30:13 +04:00
break ;
case 'F' :
2005-06-01 13:49:30 +04:00
names . Add ( "f" ) ;
2005-05-30 19:30:13 +04:00
break ;
case 'D' :
2005-06-01 13:49:30 +04:00
names . Add ( "d" ) ;
2005-05-30 19:30:13 +04:00
break ;
}
}
}
2005-06-01 13:49:30 +04:00
ParameterBuilder [ ] parameterBuilders = new ParameterBuilder [ names . Count ] ;
Hashtable clashes = new Hashtable ( ) ;
for ( int i = 0 ; i < names . Count ; i + + )
2005-05-30 19:30:13 +04:00
{
2005-06-01 13:49:30 +04:00
string name = ( string ) names [ i ] ;
if ( parameterNames ! = null & & parameterNames [ i ] ! = null )
2005-05-30 19:30:13 +04:00
{
2005-06-01 13:49:30 +04:00
name = parameterNames [ i ] ;
}
ParameterBuilder pb ;
if ( names . IndexOf ( name , i + 1 ) > = 0 | | clashes . ContainsKey ( name ) )
{
int clash = 1 ;
if ( clashes . ContainsKey ( name ) )
{
clash = ( int ) clashes [ name ] + 1 ;
}
clashes [ name ] = clash ;
name + = clash ;
2005-05-30 19:30:13 +04:00
}
2005-06-01 13:49:30 +04:00
if ( mb is MethodBuilder )
{
pb = ( ( MethodBuilder ) mb ) . DefineParameter ( i + 1 , ParameterAttributes . None , name ) ;
}
else
{
pb = ( ( ConstructorBuilder ) mb ) . DefineParameter ( i + 1 , ParameterAttributes . None , name ) ;
}
parameterBuilders [ i ] = pb ;
2005-05-30 19:30:13 +04:00
}
2005-06-01 13:49:30 +04:00
return parameterBuilders ;
2004-03-08 18:18:47 +03:00
}
2005-06-01 13:49:30 +04:00
private static string GetParameterName ( string type )
2004-01-18 01:46:43 +03:00
{
2005-06-01 13:49:30 +04:00
if ( type = = "java.lang.String" )
2005-05-30 19:30:13 +04:00
{
2005-06-01 13:49:30 +04:00
return "str" ;
2005-05-30 19:30:13 +04:00
}
2005-06-01 13:49:30 +04:00
else if ( type = = "java.lang.Object" )
2005-05-30 19:30:13 +04:00
{
2005-06-01 13:49:30 +04:00
return "obj" ;
2005-05-30 19:30:13 +04:00
}
else
{
2005-06-01 13:49:30 +04:00
System . Text . StringBuilder sb = new System . Text . StringBuilder ( ) ;
for ( int i = type . LastIndexOf ( '.' ) + 1 ; i < type . Length ; i + + )
{
if ( char . IsUpper ( type , i ) )
{
sb . Append ( char . ToLower ( type [ i ] ) ) ;
}
}
return sb . ToString ( ) ;
2005-05-30 19:30:13 +04:00
}
}
2005-06-01 13:49:30 +04:00
protected virtual void AddParameterNames ( ClassFile classFile , ClassFile . Method m , MethodBase method )
2005-05-30 19:30:13 +04:00
{
2006-02-22 17:44:07 +03:00
if ( ( JVM . IsStaticCompiler & & classFile . IsPublic & & ( m . IsPublic | | m . IsProtected ) ) | | JVM . Debug | | DynamicClassLoader . IsSaveDebugImage )
2005-05-30 19:30:13 +04:00
{
2005-06-01 13:49:30 +04:00
AddParameterNames ( method , m , null ) ;
2005-05-30 19:30:13 +04:00
}
}
2005-06-01 13:49:30 +04:00
protected virtual bool EmitMapXmlMethodBody ( ILGenerator ilgen , ClassFile f , ClassFile . Method m )
2005-05-30 19:30:13 +04:00
{
2005-06-01 13:49:30 +04:00
return false ;
2005-05-30 19:30:13 +04:00
}
2005-06-01 13:49:30 +04:00
protected virtual bool IsPInvokeMethod ( ClassFile . Method m )
{
return false ;
}
2005-05-30 19:30:13 +04:00
2005-06-01 13:49:30 +04:00
protected virtual void EmitMapXmlMetadata ( TypeBuilder typeBuilder , ClassFile classFile , FieldWrapper [ ] fields , MethodWrapper [ ] methods )
{
}
2005-05-30 19:30:13 +04:00
2005-06-01 13:49:30 +04:00
protected virtual MethodBuilder DefineGhostMethod ( string name , MethodAttributes attribs , MethodWrapper mw )
{
return null ;
}
2005-05-30 19:30:13 +04:00
2005-06-01 13:49:30 +04:00
protected virtual void FinishGhost ( TypeBuilder typeBuilder , MethodWrapper [ ] methods )
{
}
2005-05-30 19:30:13 +04:00
2005-06-01 13:49:30 +04:00
protected virtual void FinishGhostStep2 ( )
{
}
2005-05-30 19:30:13 +04:00
2005-06-01 13:49:30 +04:00
protected virtual TypeBuilder DefineType ( TypeAttributes typeAttribs )
{
2006-03-23 14:57:41 +03:00
return classLoader . ModuleBuilder . DefineType ( classLoader . MangleTypeName ( Name ) , typeAttribs ) ;
2005-06-01 13:49:30 +04:00
}
2005-05-30 19:30:13 +04:00
2005-06-01 13:49:30 +04:00
internal override MethodBase LinkMethod ( MethodWrapper mw )
{
mw . AssertLinked ( ) ;
return impl . LinkMethod ( mw ) ;
}
2004-08-17 13:05:21 +04:00
2005-06-01 13:49:30 +04:00
internal override FieldInfo LinkField ( FieldWrapper fw )
{
fw . AssertLinked ( ) ;
return impl . LinkField ( fw ) ;
}
2005-08-24 12:14:23 +04:00
internal override void EmitRunClassConstructor ( CountingILGenerator ilgen )
{
impl . EmitRunClassConstructor ( ilgen ) ;
}
2005-10-01 15:16:11 +04:00
internal override string GetGenericSignature ( )
{
return impl . GetGenericSignature ( ) ;
}
internal override string GetGenericMethodSignature ( MethodWrapper mw )
{
MethodWrapper [ ] methods = GetMethods ( ) ;
for ( int i = 0 ; i < methods . Length ; i + + )
{
if ( methods [ i ] = = mw )
{
return impl . GetGenericMethodSignature ( i ) ;
}
}
Debug . Fail ( "Unreachable code" ) ;
return null ;
}
internal override string GetGenericFieldSignature ( FieldWrapper fw )
{
FieldWrapper [ ] fields = GetFields ( ) ;
for ( int i = 0 ; i < fields . Length ; i + + )
{
if ( fields [ i ] = = fw )
{
return impl . GetGenericFieldSignature ( i + GetMethods ( ) . Length ) ;
}
}
Debug . Fail ( "Unreachable code" ) ;
return null ;
}
internal override string [ ] GetEnclosingMethod ( )
{
return impl . GetEnclosingMethod ( ) ;
}
2005-11-01 17:01:42 +03:00
2006-04-10 13:09:09 +04:00
#if ! STATIC_COMPILER
2005-11-01 17:01:42 +03:00
internal override object [ ] GetDeclaredAnnotations ( )
{
object [ ] annotations = impl . GetDeclaredAnnotations ( ) ;
2006-04-19 19:49:54 +04:00
if ( annotations ! = null )
{
object [ ] objs = new object [ annotations . Length ] ;
for ( int i = 0 ; i < annotations . Length ; i + + )
{
objs [ i ] = JVM . Library . newAnnotation ( GetClassLoader ( ) . GetJavaClassLoader ( ) , annotations [ i ] ) ;
}
return objs ;
}
return null ;
}
internal override object [ ] GetMethodAnnotations ( MethodWrapper mw )
{
MethodWrapper [ ] methods = GetMethods ( ) ;
for ( int i = 0 ; i < methods . Length ; i + + )
{
if ( methods [ i ] = = mw )
{
object [ ] annotations = impl . GetMethodAnnotations ( i ) ;
if ( annotations ! = null )
{
object [ ] objs = new object [ annotations . Length ] ;
for ( int j = 0 ; j < annotations . Length ; j + + )
{
objs [ j ] = JVM . Library . newAnnotation ( GetClassLoader ( ) . GetJavaClassLoader ( ) , annotations [ j ] ) ;
}
return objs ;
}
return null ;
}
}
Debug . Fail ( "Unreachable code" ) ;
return null ;
}
internal override object [ ] [ ] GetParameterAnnotations ( MethodWrapper mw )
{
MethodWrapper [ ] methods = GetMethods ( ) ;
for ( int i = 0 ; i < methods . Length ; i + + )
{
if ( methods [ i ] = = mw )
{
object [ ] [ ] annotations = impl . GetParameterAnnotations ( i ) ;
if ( annotations ! = null )
{
object [ ] [ ] objs = new object [ annotations . Length ] [ ] ;
for ( int j = 0 ; j < annotations . Length ; j + + )
{
objs [ j ] = new object [ annotations [ j ] . Length ] ;
for ( int k = 0 ; k < annotations [ j ] . Length ; k + + )
{
objs [ j ] [ k ] = JVM . Library . newAnnotation ( GetClassLoader ( ) . GetJavaClassLoader ( ) , annotations [ j ] [ k ] ) ;
}
}
return objs ;
}
return null ;
}
}
Debug . Fail ( "Unreachable code" ) ;
return null ;
}
internal override object [ ] GetFieldAnnotations ( FieldWrapper fw )
{
FieldWrapper [ ] fields = GetFields ( ) ;
for ( int i = 0 ; i < fields . Length ; i + + )
2005-11-01 17:01:42 +03:00
{
2006-04-19 19:49:54 +04:00
if ( fields [ i ] = = fw )
{
object [ ] annotations = impl . GetFieldAnnotations ( i ) ;
if ( annotations ! = null )
{
object [ ] objs = new object [ annotations . Length ] ;
for ( int j = 0 ; j < annotations . Length ; j + + )
{
objs [ j ] = JVM . Library . newAnnotation ( GetClassLoader ( ) . GetJavaClassLoader ( ) , annotations [ j ] ) ;
}
return objs ;
}
return null ;
}
2005-11-01 17:01:42 +03:00
}
2006-04-19 19:49:54 +04:00
Debug . Fail ( "Unreachable code" ) ;
return null ;
2005-11-01 17:01:42 +03:00
}
internal override object GetAnnotationDefault ( MethodWrapper mw )
{
MethodWrapper [ ] methods = GetMethods ( ) ;
for ( int i = 0 ; i < methods . Length ; i + + )
{
if ( methods [ i ] = = mw )
{
2006-04-19 19:49:54 +04:00
object defVal = impl . GetMethodDefaultValue ( i ) ;
if ( defVal ! = null )
{
return JVM . Library . newAnnotationElementValue ( mw . DeclaringType . GetClassLoader ( ) . GetJavaClassLoader ( ) , mw . ReturnType . ClassObject , defVal ) ;
}
return null ;
2005-11-01 17:01:42 +03:00
}
}
Debug . Fail ( "Unreachable code" ) ;
return null ;
}
2006-04-10 13:09:09 +04:00
#endif
2004-08-17 13:05:21 +04:00
}
2005-12-07 12:06:32 +03:00
#endif // !COMPACT_FRAMEWORK
2005-03-23 12:33:18 +03:00
2005-06-01 13:49:30 +04:00
class CompiledTypeWrapper : TypeWrapper
2005-03-23 12:33:18 +03:00
{
2005-06-01 13:49:30 +04:00
private readonly Type type ;
private TypeWrapper [ ] interfaces ;
private TypeWrapper [ ] innerclasses ;
2005-08-24 12:14:23 +04:00
private MethodInfo clinitMethod ;
2005-03-23 12:33:18 +03:00
2005-06-01 13:49:30 +04:00
internal static CompiledTypeWrapper newInstance ( string name , Type type )
2005-03-23 12:33:18 +03:00
{
2005-06-01 13:49:30 +04:00
// TODO since ghost and remapped types can only exist in the core library assembly, we probably
// should be able to remove the Type.IsDefined() tests in most cases
2005-12-07 12:06:32 +03:00
if ( type . IsValueType & & AttributeHelper . IsGhostInterface ( type ) )
2005-03-23 12:33:18 +03:00
{
2005-06-01 13:49:30 +04:00
return new CompiledGhostTypeWrapper ( name , type ) ;
}
2005-12-07 12:06:32 +03:00
else if ( AttributeHelper . IsRemappedType ( type ) )
2005-06-01 13:49:30 +04:00
{
return new CompiledRemappedTypeWrapper ( name , type ) ;
}
else
{
return new CompiledTypeWrapper ( name , type ) ;
2005-03-23 12:33:18 +03:00
}
}
2005-06-01 13:49:30 +04:00
private sealed class CompiledRemappedTypeWrapper : CompiledTypeWrapper
2005-03-23 12:33:18 +03:00
{
2005-06-01 13:49:30 +04:00
private readonly Type remappedType ;
internal CompiledRemappedTypeWrapper ( string name , Type type )
: base ( name , type )
2005-03-23 12:33:18 +03:00
{
2005-12-07 12:06:32 +03:00
RemappedTypeAttribute attr = AttributeHelper . GetRemappedType ( type ) ;
if ( attr = = null )
2005-06-01 13:49:30 +04:00
{
throw new InvalidOperationException ( ) ;
}
2005-12-07 12:06:32 +03:00
remappedType = attr . Type ;
2005-03-23 12:33:18 +03:00
}
2005-06-01 13:49:30 +04:00
internal override Type TypeAsTBD
2005-03-23 12:33:18 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
return remappedType ;
}
2005-03-23 12:33:18 +03:00
}
2005-06-01 13:49:30 +04:00
internal override bool IsRemapped
2005-03-23 12:33:18 +03:00
{
2005-06-01 13:49:30 +04:00
get
2005-03-23 12:33:18 +03:00
{
2005-06-01 13:49:30 +04:00
return true ;
}
}
protected override void LazyPublishMembers ( )
{
ArrayList methods = new ArrayList ( ) ;
ArrayList fields = new ArrayList ( ) ;
MemberInfo [ ] members = type . GetMembers ( BindingFlags . DeclaredOnly | BindingFlags . Public | BindingFlags . NonPublic | BindingFlags . Static | BindingFlags . Instance ) ;
foreach ( MemberInfo m in members )
{
if ( ! AttributeHelper . IsHideFromJava ( m ) )
2005-03-23 12:33:18 +03:00
{
2005-06-01 13:49:30 +04:00
MethodBase method = m as MethodBase ;
if ( method ! = null & &
( remappedType . IsSealed | | ! m . Name . StartsWith ( "instancehelper_" ) ) & &
( ! remappedType . IsSealed | | method . IsStatic ) )
2005-03-23 12:33:18 +03:00
{
2006-04-05 12:18:58 +04:00
// FXBUG on .NET 1.1 Throwable.toString() shows up twice
2005-06-01 13:49:30 +04:00
methods . Add ( CreateRemappedMethodWrapper ( method ) ) ;
}
else
{
FieldInfo field = m as FieldInfo ;
if ( field ! = null )
{
fields . Add ( CreateFieldWrapper ( field ) ) ;
}
2005-03-23 12:33:18 +03:00
}
}
}
2005-06-01 13:49:30 +04:00
// if we're a remapped interface, we need to get the methods from the real interface
if ( remappedType . IsInterface )
2005-03-23 12:33:18 +03:00
{
2005-06-01 13:49:30 +04:00
Type nestedHelper = type . GetNestedType ( "__Helper" , BindingFlags . Public | BindingFlags . Static ) ;
2005-12-07 12:06:32 +03:00
foreach ( RemappedInterfaceMethodAttribute m in AttributeHelper . GetRemappedInterfaceMethods ( type ) )
2005-03-23 12:33:18 +03:00
{
2005-06-01 13:49:30 +04:00
MethodInfo method = remappedType . GetMethod ( m . MappedTo ) ;
MethodInfo mbHelper = method ;
2006-04-05 12:18:58 +04:00
ExModifiers modifiers = AttributeHelper . GetModifiers ( method , false ) ;
2005-06-01 13:49:30 +04:00
string name ;
string sig ;
TypeWrapper retType ;
TypeWrapper [ ] paramTypes ;
GetNameSigFromMethodBase ( method , out name , out sig , out retType , out paramTypes ) ;
if ( nestedHelper ! = null )
2005-03-23 12:33:18 +03:00
{
2005-06-01 13:49:30 +04:00
mbHelper = nestedHelper . GetMethod ( m . Name ) ;
if ( mbHelper = = null )
{
mbHelper = method ;
}
2005-03-23 12:33:18 +03:00
}
2005-06-01 13:49:30 +04:00
methods . Add ( new CompiledRemappedMethodWrapper ( this , m . Name , sig , method , retType , paramTypes , modifiers , false , mbHelper , null ) ) ;
2005-03-23 12:33:18 +03:00
}
}
2005-06-01 13:49:30 +04:00
SetMethods ( ( MethodWrapper [ ] ) methods . ToArray ( typeof ( MethodWrapper ) ) ) ;
SetFields ( ( FieldWrapper [ ] ) fields . ToArray ( typeof ( FieldWrapper ) ) ) ;
2005-03-23 12:33:18 +03:00
}
2005-06-01 13:49:30 +04:00
private MethodWrapper CreateRemappedMethodWrapper ( MethodBase mb )
2005-03-23 12:33:18 +03:00
{
2006-04-05 12:18:58 +04:00
ExModifiers modifiers = AttributeHelper . GetModifiers ( mb , false ) ;
2005-06-01 13:49:30 +04:00
string name ;
string sig ;
TypeWrapper retType ;
TypeWrapper [ ] paramTypes ;
GetNameSigFromMethodBase ( mb , out name , out sig , out retType , out paramTypes ) ;
MethodInfo mbHelper = mb as MethodInfo ;
2006-04-05 12:18:58 +04:00
bool hideFromReflection = mbHelper ! = null & & AttributeHelper . IsHideFromReflection ( mbHelper ) ;
2005-06-01 13:49:30 +04:00
MethodInfo mbNonvirtualHelper = null ;
if ( ! mb . IsStatic & & ! mb . IsConstructor )
{
ParameterInfo [ ] parameters = mb . GetParameters ( ) ;
Type [ ] argTypes = new Type [ parameters . Length + 1 ] ;
argTypes [ 0 ] = remappedType ;
for ( int i = 0 ; i < parameters . Length ; i + + )
{
argTypes [ i + 1 ] = parameters [ i ] . ParameterType ;
}
MethodInfo helper = type . GetMethod ( "instancehelper_" + mb . Name , BindingFlags . NonPublic | BindingFlags . Public | BindingFlags . Static , null , argTypes , null ) ;
if ( helper ! = null )
{
mbHelper = helper ;
}
mbNonvirtualHelper = type . GetMethod ( "nonvirtualhelper/" + mb . Name , BindingFlags . NonPublic | BindingFlags . Static , null , argTypes , null ) ;
2005-03-23 12:33:18 +03:00
}
2006-04-05 12:18:58 +04:00
return new CompiledRemappedMethodWrapper ( this , name , sig , mb , retType , paramTypes , modifiers , hideFromReflection , mbHelper , mbNonvirtualHelper ) ;
2005-03-23 12:33:18 +03:00
}
}
2005-06-01 13:49:30 +04:00
private sealed class CompiledGhostTypeWrapper : CompiledTypeWrapper
2005-03-23 12:33:18 +03:00
{
2005-06-01 13:49:30 +04:00
private FieldInfo ghostRefField ;
private Type typeAsBaseType ;
2005-03-23 12:33:18 +03:00
2005-06-01 13:49:30 +04:00
internal CompiledGhostTypeWrapper ( string name , Type type )
: base ( name , type )
{
}
internal override Type TypeAsBaseType
2005-03-23 12:33:18 +03:00
{
2005-06-01 13:49:30 +04:00
get
2005-03-23 12:33:18 +03:00
{
2005-06-01 13:49:30 +04:00
if ( typeAsBaseType = = null )
{
typeAsBaseType = type . GetNestedType ( "__Interface" ) ;
}
return typeAsBaseType ;
2005-03-23 12:33:18 +03:00
}
}
2005-06-01 13:49:30 +04:00
internal override FieldInfo GhostRefField
2005-03-23 12:33:18 +03:00
{
2005-06-01 13:49:30 +04:00
get
2005-03-23 12:33:18 +03:00
{
2005-06-01 13:49:30 +04:00
if ( ghostRefField = = null )
{
ghostRefField = type . GetField ( "__<ref>" ) ;
}
return ghostRefField ;
2005-03-23 12:33:18 +03:00
}
}
2005-06-01 13:49:30 +04:00
internal override bool IsGhost
2005-03-23 12:33:18 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
return true ;
}
2005-03-23 12:33:18 +03:00
}
}
2004-01-11 16:14:42 +03:00
2005-06-01 13:49:30 +04:00
internal static string GetName ( Type type )
2002-12-18 19:00:25 +03:00
{
2005-12-07 12:06:32 +03:00
Debug . Assert ( AttributeHelper . IsJavaModule ( type . Module ) ) ;
2002-12-18 19:00:25 +03:00
2005-06-01 13:49:30 +04:00
// look for our custom attribute, that contains the real name of the type (for inner classes)
2005-12-07 12:06:32 +03:00
InnerClassAttribute attr = AttributeHelper . GetInnerClass ( type ) ;
if ( attr ! = null )
2005-06-01 13:49:30 +04:00
{
2005-12-07 12:06:32 +03:00
string name = attr . InnerClassName ;
2005-07-07 15:24:08 +04:00
if ( name ! = null )
{
return name ;
}
return GetName ( type . DeclaringType ) + "$" + type . Name ;
2005-06-01 13:49:30 +04:00
}
return type . FullName ;
2003-08-13 19:00:41 +04:00
}
2005-06-01 13:49:30 +04:00
// TODO consider resolving the baseType lazily
private static TypeWrapper GetBaseTypeWrapper ( Type type )
2003-08-13 19:00:41 +04:00
{
2005-12-07 12:06:32 +03:00
if ( type . IsInterface | | AttributeHelper . IsGhostInterface ( type ) )
2004-03-08 18:18:47 +03:00
{
2005-06-01 13:49:30 +04:00
return null ;
}
else if ( type . BaseType = = null )
{
// System.Object must appear to be derived from java.lang.Object
return CoreClasses . java . lang . Object . Wrapper ;
}
else
{
2005-12-07 12:06:32 +03:00
RemappedTypeAttribute attr = AttributeHelper . GetRemappedType ( type ) ;
if ( attr ! = null )
2004-03-08 18:18:47 +03:00
{
2005-12-07 12:06:32 +03:00
if ( attr . Type = = typeof ( object ) )
2005-06-01 13:49:30 +04:00
{
return null ;
}
else
{
return CoreClasses . java . lang . Object . Wrapper ;
}
2004-03-08 18:18:47 +03:00
}
2005-06-01 13:49:30 +04:00
return ClassLoaderWrapper . GetWrapperFromType ( type . BaseType ) ;
2004-03-08 18:18:47 +03:00
}
2003-08-13 19:00:41 +04:00
}
2002-12-18 19:00:25 +03:00
2005-11-01 17:01:42 +03:00
internal override TypeWrapper MakeArrayType ( int rank )
{
Debug . Assert ( rank ! = 0 ) ;
// NOTE this call to LoadClassByDottedNameFast can never fail and will not trigger a class load
return ClassLoaderWrapper . GetBootstrapClassLoader ( ) . LoadClassByDottedNameFast ( new String ( '[' , rank ) + this . SigName ) ;
}
2006-04-05 12:18:58 +04:00
private CompiledTypeWrapper ( ExModifiers exmod , string name , TypeWrapper baseTypeWrapper )
: base ( exmod . Modifiers , name , baseTypeWrapper )
{
this . IsInternal = exmod . IsInternal ;
}
2005-06-01 13:49:30 +04:00
private CompiledTypeWrapper ( string name , Type type )
2006-04-05 12:18:58 +04:00
: this ( GetModifiers ( type ) , name , GetBaseTypeWrapper ( type ) )
2003-05-30 16:08:59 +04:00
{
2005-06-01 13:49:30 +04:00
Debug . Assert ( ! ( type is TypeBuilder ) ) ;
Debug . Assert ( ! type . IsArray ) ;
this . type = type ;
2003-05-30 16:08:59 +04:00
}
2005-06-01 13:49:30 +04:00
2006-03-23 14:57:41 +03:00
internal override ClassLoaderWrapper GetClassLoader ( )
{
return JVM . IsStaticCompiler | | ClassLoaderWrapper . IsCoreAssemblyType ( type ) ? ClassLoaderWrapper . GetBootstrapClassLoader ( ) : ClassLoaderWrapper . GetSystemClassLoader ( ) ;
}
2006-04-05 12:18:58 +04:00
private static ExModifiers GetModifiers ( Type type )
2002-12-18 19:00:25 +03:00
{
2005-12-07 12:06:32 +03:00
ModifiersAttribute attr = AttributeHelper . GetModifiersAttribute ( type ) ;
if ( attr ! = null )
2005-06-01 13:49:30 +04:00
{
2006-04-05 12:18:58 +04:00
return new ExModifiers ( attr . Modifiers , attr . IsInternal ) ;
2005-06-01 13:49:30 +04:00
}
// only returns public, protected, private, final, static, abstract and interface (as per
// the documentation of Class.getModifiers())
Modifiers modifiers = 0 ;
if ( type . IsPublic )
{
modifiers | = Modifiers . Public ;
}
// TODO do we really need to look for nested attributes? I think all inner classes will have the ModifiersAttribute.
else if ( type . IsNestedPublic )
{
modifiers | = Modifiers . Public | Modifiers . Static ;
}
else if ( type . IsNestedPrivate )
{
modifiers | = Modifiers . Private | Modifiers . Static ;
}
else if ( type . IsNestedFamily | | type . IsNestedFamORAssem )
{
modifiers | = Modifiers . Protected | Modifiers . Static ;
}
else if ( type . IsNestedAssembly | | type . IsNestedFamANDAssem )
{
modifiers | = Modifiers . Static ;
}
if ( type . IsSealed )
{
modifiers | = Modifiers . Final ;
}
if ( type . IsAbstract )
{
modifiers | = Modifiers . Abstract ;
}
if ( type . IsInterface )
{
modifiers | = Modifiers . Interface ;
}
2006-04-05 12:18:58 +04:00
return new ExModifiers ( modifiers , false ) ;
2002-12-18 19:00:25 +03:00
}
2005-06-01 13:49:30 +04:00
internal override bool HasStaticInitializer
2004-09-15 17:35:44 +04:00
{
2005-06-01 13:49:30 +04:00
get
{
2005-08-24 12:14:23 +04:00
// trigger LazyPublishMembers
GetMethods ( ) ;
return clinitMethod ! = null ;
2005-06-01 13:49:30 +04:00
}
2004-09-15 17:35:44 +04:00
}
2005-06-01 13:49:30 +04:00
internal override Assembly Assembly
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
get
{
return type . Assembly ;
}
2004-08-17 13:05:21 +04:00
}
2005-06-01 13:49:30 +04:00
internal override TypeWrapper [ ] Interfaces
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
get
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
if ( interfaces = = null )
2004-05-14 13:31:54 +04:00
{
2005-06-01 13:49:30 +04:00
// NOTE instead of getting the interfaces list from Type, we use a custom
// attribute to list the implemented interfaces, because Java reflection only
// reports the interfaces *directly* implemented by the type, not the inherited
// interfaces. This is significant for serialVersionUID calculation (for example).
2005-12-07 12:06:32 +03:00
ImplementsAttribute attr = AttributeHelper . GetImplements ( type ) ;
if ( attr ! = null )
2005-06-01 13:49:30 +04:00
{
2005-12-07 12:06:32 +03:00
string [ ] interfaceNames = attr . Interfaces ;
2005-06-01 13:49:30 +04:00
TypeWrapper [ ] interfaceWrappers = new TypeWrapper [ interfaceNames . Length ] ;
for ( int i = 0 ; i < interfaceWrappers . Length ; i + + )
{
interfaceWrappers [ i ] = GetClassLoader ( ) . LoadClassByDottedName ( interfaceNames [ i ] ) ;
}
this . interfaces = interfaceWrappers ;
}
else
2004-05-14 13:31:54 +04:00
{
2005-06-01 13:49:30 +04:00
interfaces = TypeWrapper . EmptyArray ;
2004-05-14 13:31:54 +04:00
}
2002-12-18 19:00:25 +03:00
}
2005-06-01 13:49:30 +04:00
return interfaces ;
2002-12-18 19:00:25 +03:00
}
}
2005-06-01 13:49:30 +04:00
internal override TypeWrapper [ ] InnerClasses
2003-02-18 12:30:34 +03:00
{
2005-06-01 13:49:30 +04:00
get
2003-02-18 12:30:34 +03:00
{
2005-06-01 13:49:30 +04:00
// TODO why are we caching this?
if ( innerclasses = = null )
2003-02-20 17:18:38 +03:00
{
2005-06-01 13:49:30 +04:00
Type [ ] nestedTypes = type . GetNestedTypes ( BindingFlags . Public | BindingFlags . NonPublic | BindingFlags . DeclaredOnly ) ;
ArrayList wrappers = new ArrayList ( ) ;
for ( int i = 0 ; i < nestedTypes . Length ; i + + )
2003-10-17 12:08:31 +04:00
{
2005-06-01 13:49:30 +04:00
if ( ! AttributeHelper . IsHideFromJava ( nestedTypes [ i ] ) )
{
wrappers . Add ( ClassLoaderWrapper . GetWrapperFromType ( nestedTypes [ i ] ) ) ;
}
2003-10-17 12:08:31 +04:00
}
2005-06-01 13:49:30 +04:00
innerclasses = ( TypeWrapper [ ] ) wrappers . ToArray ( typeof ( TypeWrapper ) ) ;
2003-02-20 17:18:38 +03:00
}
2005-06-01 13:49:30 +04:00
return innerclasses ;
2003-02-18 12:30:34 +03:00
}
}
2005-06-01 13:49:30 +04:00
internal override TypeWrapper DeclaringTypeWrapper
2003-02-18 12:30:34 +03:00
{
2005-06-01 13:49:30 +04:00
get
2003-02-20 17:18:38 +03:00
{
2005-06-01 13:49:30 +04:00
Type declaringType = type . DeclaringType ;
if ( declaringType ! = null )
{
return ClassLoaderWrapper . GetWrapperFromType ( declaringType ) ;
}
return null ;
2003-02-20 17:18:38 +03:00
}
2003-02-18 12:30:34 +03:00
}
2005-06-01 13:49:30 +04:00
internal override Modifiers ReflectiveModifiers
2003-05-30 16:08:59 +04:00
{
2005-06-01 13:49:30 +04:00
get
2003-05-30 16:08:59 +04:00
{
2005-12-07 12:06:32 +03:00
InnerClassAttribute attr = AttributeHelper . GetInnerClass ( type ) ;
if ( attr ! = null )
2005-06-01 13:49:30 +04:00
{
2005-12-07 12:06:32 +03:00
return attr . Modifiers ;
2005-06-01 13:49:30 +04:00
}
return Modifiers ;
2004-08-17 13:05:21 +04:00
}
}
2005-06-01 13:49:30 +04:00
internal override Type TypeAsBaseType
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
get
{
return type ;
}
2004-08-17 13:05:21 +04:00
}
2005-06-01 13:49:30 +04:00
private void SigTypePatchUp ( string sigtype , ref TypeWrapper type )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
if ( sigtype ! = type . SigName )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
// if type is an array, we know that it is a ghost array, because arrays of unloadable are compiled
// as object (not as arrays of object)
if ( type . IsArray )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
type = GetClassLoader ( ) . FieldTypeWrapperFromSig ( sigtype ) ;
}
else
{
if ( sigtype [ 0 ] = = 'L' )
{
sigtype = sigtype . Substring ( 1 , sigtype . Length - 2 ) ;
}
type = new UnloadableTypeWrapper ( sigtype ) ;
2004-08-17 13:05:21 +04:00
}
2003-05-30 16:08:59 +04:00
}
}
2005-06-01 13:49:30 +04:00
private static void ParseSig ( string sig , out string [ ] sigparam , out string sigret )
2003-10-17 12:08:31 +04:00
{
2005-06-01 13:49:30 +04:00
ArrayList list = new ArrayList ( ) ;
int pos = 1 ;
for ( ; ; )
2003-10-17 12:08:31 +04:00
{
2005-06-01 13:49:30 +04:00
switch ( sig [ pos ] )
2003-10-17 12:08:31 +04:00
{
2005-06-01 13:49:30 +04:00
case 'L' :
2004-08-17 13:05:21 +04:00
{
int end = sig . IndexOf ( ';' , pos ) + 1 ;
list . Add ( sig . Substring ( pos , end - pos ) ) ;
pos = end ;
2005-06-01 13:49:30 +04:00
break ;
2004-08-17 13:05:21 +04:00
}
2005-06-01 13:49:30 +04:00
case '[' :
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
int skip = 1 ;
while ( sig [ pos + skip ] = = '[' ) skip + + ;
if ( sig [ pos + skip ] = = 'L' )
{
int end = sig . IndexOf ( ';' , pos ) + 1 ;
list . Add ( sig . Substring ( pos , end - pos ) ) ;
pos = end ;
}
else
{
skip + + ;
list . Add ( sig . Substring ( pos , skip ) ) ;
pos + = skip ;
}
break ;
2004-08-17 13:05:21 +04:00
}
2005-06-01 13:49:30 +04:00
case ')' :
sigparam = ( string [ ] ) list . ToArray ( typeof ( string ) ) ;
sigret = sig . Substring ( pos + 1 ) ;
return ;
default :
list . Add ( sig . Substring ( pos , 1 ) ) ;
pos + + ;
break ;
2003-10-17 12:08:31 +04:00
}
}
}
2005-06-01 13:49:30 +04:00
private void GetNameSigFromMethodBase ( MethodBase method , out string name , out string sig , out TypeWrapper retType , out TypeWrapper [ ] paramTypes )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
retType = method is ConstructorInfo ? PrimitiveTypeWrapper . VOID : ClassLoaderWrapper . GetWrapperFromType ( ( ( MethodInfo ) method ) . ReturnType ) ;
ParameterInfo [ ] parameters = method . GetParameters ( ) ;
paramTypes = new TypeWrapper [ parameters . Length ] ;
for ( int i = 0 ; i < parameters . Length ; i + + )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
paramTypes [ i ] = ClassLoaderWrapper . GetWrapperFromType ( parameters [ i ] . ParameterType ) ;
2004-08-17 13:05:21 +04:00
}
2005-12-07 12:06:32 +03:00
NameSigAttribute attr = AttributeHelper . GetNameSig ( method ) ;
if ( attr ! = null )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
name = attr . Name ;
sig = attr . Sig ;
string [ ] sigparams ;
string sigret ;
ParseSig ( sig , out sigparams , out sigret ) ;
// HACK newhelper methods have a return type, but it should be void
if ( name = = "<init>" )
{
retType = PrimitiveTypeWrapper . VOID ;
}
SigTypePatchUp ( sigret , ref retType ) ;
// if we have a remapped method, the paramTypes array contains an additional entry for "this" so we have
// to remove that
if ( paramTypes . Length = = sigparams . Length + 1 )
{
TypeWrapper [ ] temp = paramTypes ;
paramTypes = new TypeWrapper [ sigparams . Length ] ;
Array . Copy ( temp , 1 , paramTypes , 0 , paramTypes . Length ) ;
}
Debug . Assert ( sigparams . Length = = paramTypes . Length ) ;
for ( int i = 0 ; i < sigparams . Length ; i + + )
{
SigTypePatchUp ( sigparams [ i ] , ref paramTypes [ i ] ) ;
}
2004-08-17 13:05:21 +04:00
}
else
{
2005-06-01 13:49:30 +04:00
if ( method is ConstructorInfo )
{
name = method . IsStatic ? "<clinit>" : "<init>" ;
}
else
{
name = method . Name ;
}
System . Text . StringBuilder sb = new System . Text . StringBuilder ( "(" ) ;
foreach ( TypeWrapper tw in paramTypes )
{
sb . Append ( tw . SigName ) ;
}
sb . Append ( ")" ) ;
sb . Append ( retType . SigName ) ;
sig = sb . ToString ( ) ;
2004-08-17 13:05:21 +04:00
}
2003-10-17 12:08:31 +04:00
}
2005-06-01 13:49:30 +04:00
protected override void LazyPublishMembers ( )
2004-03-08 18:18:47 +03:00
{
2005-08-24 12:14:23 +04:00
clinitMethod = type . GetMethod ( "__<clinit>" , BindingFlags . Static | BindingFlags . Public | BindingFlags . NonPublic ) ;
2005-06-01 13:49:30 +04:00
ArrayList methods = new ArrayList ( ) ;
ArrayList fields = new ArrayList ( ) ;
MemberInfo [ ] members = type . GetMembers ( BindingFlags . DeclaredOnly | BindingFlags . Public | BindingFlags . NonPublic | BindingFlags . Static | BindingFlags . Instance ) ;
foreach ( MemberInfo m in members )
2004-03-08 18:18:47 +03:00
{
2005-06-01 13:49:30 +04:00
if ( ! AttributeHelper . IsHideFromJava ( m ) )
2005-03-23 12:33:18 +03:00
{
2005-06-01 13:49:30 +04:00
MethodBase method = m as MethodBase ;
if ( method ! = null )
2004-07-10 11:19:42 +04:00
{
2005-08-24 12:14:23 +04:00
if ( method . IsSpecialName & &
( method . Name = = "op_Implicit" | | method . Name . StartsWith ( "__<" ) ) )
2005-07-07 18:03:21 +04:00
{
// skip
}
else
{
string name ;
string sig ;
TypeWrapper retType ;
TypeWrapper [ ] paramTypes ;
GetNameSigFromMethodBase ( method , out name , out sig , out retType , out paramTypes ) ;
MethodInfo mi = method as MethodInfo ;
2005-08-14 19:49:50 +04:00
bool hideFromReflection = mi ! = null ? AttributeHelper . IsHideFromReflection ( mi ) : false ;
MemberFlags flags = hideFromReflection ? MemberFlags . HideFromReflection : MemberFlags . None ;
2006-04-05 12:18:58 +04:00
ExModifiers mods = AttributeHelper . GetModifiers ( method , false ) ;
if ( mods . IsInternal )
{
flags | = MemberFlags . InternalAccess ;
}
methods . Add ( MethodWrapper . Create ( this , name , sig , method , retType , paramTypes , mods . Modifiers , flags ) ) ;
2005-07-07 18:03:21 +04:00
}
2005-06-01 13:49:30 +04:00
}
else
{
FieldInfo field = m as FieldInfo ;
if ( field ! = null )
{
2005-07-07 18:03:21 +04:00
if ( field . IsSpecialName & & field . Name . StartsWith ( "__<" ) )
{
// skip
}
else
{
fields . Add ( CreateFieldWrapper ( field ) ) ;
}
2005-06-01 13:49:30 +04:00
}
2005-08-14 19:49:50 +04:00
else
{
PropertyInfo property = m as PropertyInfo ;
if ( property ! = null )
{
// Only AccessStub properties (marked by HideFromReflectionAttribute)
// are considered here
if ( AttributeHelper . IsHideFromReflection ( property ) )
{
fields . Add ( new CompiledAccessStubFieldWrapper ( this , property ) ) ;
}
}
}
2004-07-10 11:19:42 +04:00
}
2004-03-08 18:18:47 +03:00
}
}
2005-06-01 13:49:30 +04:00
SetMethods ( ( MethodWrapper [ ] ) methods . ToArray ( typeof ( MethodWrapper ) ) ) ;
SetFields ( ( FieldWrapper [ ] ) fields . ToArray ( typeof ( FieldWrapper ) ) ) ;
2004-03-08 18:18:47 +03:00
}
2004-06-14 14:36:38 +04:00
2005-06-01 13:49:30 +04:00
private class CompiledRemappedMethodWrapper : SmartMethodWrapper
2004-06-14 14:36:38 +04:00
{
2005-06-01 13:49:30 +04:00
private MethodInfo mbHelper ;
private MethodInfo mbNonvirtualHelper ;
2004-06-14 14:36:38 +04:00
2006-04-05 12:18:58 +04:00
internal CompiledRemappedMethodWrapper ( TypeWrapper declaringType , string name , string sig , MethodBase method , TypeWrapper returnType , TypeWrapper [ ] parameterTypes , ExModifiers modifiers , bool hideFromReflection , MethodInfo mbHelper , MethodInfo mbNonvirtualHelper )
: base ( declaringType , name , sig , method , returnType , parameterTypes , modifiers . Modifiers ,
( modifiers . IsInternal ? MemberFlags . InternalAccess : MemberFlags . None ) | ( hideFromReflection ? MemberFlags . HideFromReflection : MemberFlags . None ) )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
this . mbHelper = mbHelper ;
this . mbNonvirtualHelper = mbNonvirtualHelper ;
2004-08-17 13:05:21 +04:00
}
2005-12-07 12:06:32 +03:00
#if ! COMPACT_FRAMEWORK
2005-06-01 13:49:30 +04:00
protected override void CallImpl ( ILGenerator ilgen )
2004-06-14 14:36:38 +04:00
{
2005-06-01 13:49:30 +04:00
MethodBase mb = GetMethod ( ) ;
MethodInfo mi = mb as MethodInfo ;
if ( mi ! = null )
{
ilgen . Emit ( OpCodes . Call , mi ) ;
}
else
{
ilgen . Emit ( OpCodes . Call , ( ConstructorInfo ) mb ) ;
}
2004-06-14 14:36:38 +04:00
}
2005-06-01 13:49:30 +04:00
protected override void CallvirtImpl ( ILGenerator ilgen )
2004-06-14 14:36:38 +04:00
{
2005-06-01 13:49:30 +04:00
Debug . Assert ( ! mbHelper . IsStatic | | mbHelper . Name . StartsWith ( "instancehelper_" ) | | mbHelper . DeclaringType . Name = = "__Helper" ) ;
ilgen . Emit ( mbHelper . IsStatic ? OpCodes . Call : OpCodes . Callvirt , mbHelper ) ;
2004-06-14 14:36:38 +04:00
}
2004-08-17 13:05:21 +04:00
2005-06-01 13:49:30 +04:00
protected override void NewobjImpl ( ILGenerator ilgen )
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
MethodBase mb = GetMethod ( ) ;
MethodInfo mi = mb as MethodInfo ;
if ( mi ! = null )
2003-09-10 18:58:19 +04:00
{
2005-06-01 13:49:30 +04:00
Debug . Assert ( mi . Name = = "newhelper" ) ;
ilgen . Emit ( OpCodes . Call , mi ) ;
2003-07-02 18:50:35 +04:00
}
2005-06-01 13:49:30 +04:00
else
2003-07-02 18:50:35 +04:00
{
2005-06-01 13:49:30 +04:00
ilgen . Emit ( OpCodes . Newobj , ( ConstructorInfo ) mb ) ;
2003-07-02 18:50:35 +04:00
}
2005-06-01 13:49:30 +04:00
}
2005-12-07 12:06:32 +03:00
#endif
2005-06-01 13:49:30 +04:00
2006-04-10 13:09:09 +04:00
#if ! STATIC_COMPILER
2005-06-01 13:49:30 +04:00
[HideFromJava]
internal override object Invoke ( object obj , object [ ] args , bool nonVirtual )
{
MethodBase mb ;
if ( nonVirtual )
2004-03-08 18:18:47 +03:00
{
2005-06-01 13:49:30 +04:00
if ( DeclaringType . TypeAsBaseType . IsInstanceOfType ( obj ) )
{
mb = GetMethod ( ) ;
}
else if ( mbNonvirtualHelper ! = null )
{
mb = mbNonvirtualHelper ;
}
else if ( mbHelper ! = null )
{
mb = mbHelper ;
}
else
{
// we can end up here if someone calls a constructor with nonVirtual set (which is pointless, but legal)
mb = GetMethod ( ) ;
}
2004-03-08 18:18:47 +03:00
}
else
{
2005-06-01 13:49:30 +04:00
mb = mbHelper ! = null ? mbHelper : GetMethod ( ) ;
2004-03-08 18:18:47 +03:00
}
2005-06-01 13:49:30 +04:00
return InvokeImpl ( mb , obj , args , nonVirtual ) ;
2004-03-08 18:18:47 +03:00
}
2006-04-10 13:09:09 +04:00
#endif // !STATIC_COMPILER
2005-10-01 15:16:11 +04:00
internal string GetGenericSignature ( )
{
object [ ] attr = ( mbHelper ! = null ? mbHelper : GetMethod ( ) ) . GetCustomAttributes ( typeof ( SignatureAttribute ) , false ) ;
if ( attr . Length = = 1 )
{
return ( ( SignatureAttribute ) attr [ 0 ] ) . Signature ;
}
return null ;
}
2004-10-04 23:30:53 +04:00
}
2004-01-28 14:28:16 +03:00
2005-06-01 13:49:30 +04:00
private FieldWrapper CreateFieldWrapper ( FieldInfo field )
2002-12-18 19:00:25 +03:00
{
2006-04-05 12:18:58 +04:00
ExModifiers modifiers = AttributeHelper . GetModifiers ( field , false ) ;
2005-06-01 13:49:30 +04:00
string name = field . Name ;
TypeWrapper type = ClassLoaderWrapper . GetWrapperFromType ( field . FieldType ) ;
2005-12-07 12:06:32 +03:00
NameSigAttribute attr = AttributeHelper . GetNameSig ( field ) ;
if ( attr ! = null )
2005-06-01 13:49:30 +04:00
{
name = attr . Name ;
SigTypePatchUp ( attr . Sig , ref type ) ;
}
2002-12-18 19:00:25 +03:00
2005-06-01 13:49:30 +04:00
// If the backing field is private, but the modifiers aren't, we've got a final field that
// has a property accessor method.
2006-04-05 12:18:58 +04:00
if ( field . IsPrivate & & ( ( modifiers . Modifiers & Modifiers . Private ) = = 0 ) )
2005-06-01 13:49:30 +04:00
{
BindingFlags bindingFlags = BindingFlags . DeclaredOnly | BindingFlags . NonPublic | BindingFlags . Public ;
bindingFlags | = field . IsStatic ? BindingFlags . Static : BindingFlags . Instance ;
PropertyInfo prop = field . DeclaringType . GetProperty ( field . Name , bindingFlags , null , field . FieldType , Type . EmptyTypes , null ) ;
MethodInfo getter = prop . GetGetMethod ( true ) ;
return new GetterFieldWrapper ( this , type , field , name , type . SigName , modifiers , getter ) ;
}
else if ( field . IsLiteral )
{
2005-08-14 19:49:50 +04:00
MemberFlags flags = MemberFlags . LiteralField ;
if ( AttributeHelper . IsHideFromReflection ( field ) )
{
flags | = MemberFlags . HideFromReflection ;
}
2006-04-05 12:18:58 +04:00
if ( modifiers . IsInternal )
{
flags | = MemberFlags . InternalAccess ;
}
return new ConstantFieldWrapper ( this , type , name , type . SigName , modifiers . Modifiers , field , null , flags ) ;
2005-06-01 13:49:30 +04:00
}
else
{
return FieldWrapper . Create ( this , type , field , name , type . SigName , modifiers ) ;
}
2004-03-08 18:18:47 +03:00
}
2005-06-01 13:49:30 +04:00
internal override Type TypeAsTBD
2004-03-08 18:18:47 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
return type ;
}
2002-12-18 19:00:25 +03:00
}
2004-10-04 23:30:53 +04:00
2005-06-01 13:49:30 +04:00
internal override bool IsMapUnsafeException
2003-02-22 15:28:12 +03:00
{
2005-06-01 13:49:30 +04:00
get
2004-07-10 11:19:42 +04:00
{
2005-12-07 12:06:32 +03:00
return AttributeHelper . IsExceptionIsUnsafeForMapping ( type ) ;
2004-07-10 11:19:42 +04:00
}
2003-02-22 15:28:12 +03:00
}
2003-10-22 20:34:22 +04:00
2005-08-05 12:40:54 +04:00
internal override void Finish ( )
2003-10-22 20:34:22 +04:00
{
2006-03-01 15:26:25 +03:00
if ( BaseTypeWrapper ! = null )
{
BaseTypeWrapper . Finish ( ) ;
}
foreach ( TypeWrapper tw in this . Interfaces )
{
tw . Finish ( ) ;
}
2003-10-22 20:34:22 +04:00
}
2005-08-24 12:14:23 +04:00
2005-12-07 12:06:32 +03:00
#if ! COMPACT_FRAMEWORK
2005-08-24 12:14:23 +04:00
internal override void EmitRunClassConstructor ( ILGenerator ilgen )
{
// trigger LazyPublishMembers
GetMethods ( ) ;
if ( clinitMethod ! = null )
{
ilgen . Emit ( OpCodes . Call , clinitMethod ) ;
}
}
2005-12-07 12:06:32 +03:00
#endif
2005-10-01 15:16:11 +04:00
internal override string GetGenericSignature ( )
{
object [ ] attr = type . GetCustomAttributes ( typeof ( SignatureAttribute ) , false ) ;
if ( attr . Length = = 1 )
{
return ( ( SignatureAttribute ) attr [ 0 ] ) . Signature ;
}
return null ;
}
internal override string GetGenericMethodSignature ( MethodWrapper mw )
{
if ( mw is CompiledRemappedMethodWrapper )
{
return ( ( CompiledRemappedMethodWrapper ) mw ) . GetGenericSignature ( ) ;
}
MethodBase mb = mw . GetMethod ( ) ;
if ( mb ! = null )
{
object [ ] attr = mb . GetCustomAttributes ( typeof ( SignatureAttribute ) , false ) ;
if ( attr . Length = = 1 )
{
return ( ( SignatureAttribute ) attr [ 0 ] ) . Signature ;
}
}
return null ;
}
internal override string GetGenericFieldSignature ( FieldWrapper fw )
{
FieldInfo fi = fw . GetField ( ) ;
if ( fi ! = null )
{
object [ ] attr = fi . GetCustomAttributes ( typeof ( SignatureAttribute ) , false ) ;
if ( attr . Length = = 1 )
{
return ( ( SignatureAttribute ) attr [ 0 ] ) . Signature ;
}
}
return null ;
}
internal override string [ ] GetEnclosingMethod ( )
{
object [ ] attr = type . GetCustomAttributes ( typeof ( EnclosingMethodAttribute ) , false ) ;
if ( attr . Length = = 1 )
{
EnclosingMethodAttribute enc = ( EnclosingMethodAttribute ) attr [ 0 ] ;
return new string [ ] { enc . ClassName , enc . MethodName , enc . MethodSignature } ;
}
return null ;
}
2005-11-01 17:01:42 +03:00
internal override object [ ] GetDeclaredAnnotations ( )
{
return type . GetCustomAttributes ( false ) ;
}
2005-12-07 12:06:32 +03:00
#if ! COMPACT_FRAMEWORK
2005-11-01 17:01:42 +03:00
private class CompiledAnnotation : Annotation
{
private Type type ;
internal CompiledAnnotation ( Type type )
{
this . type = type ;
}
internal override void Apply ( TypeBuilder tb , object annotation )
{
// TODO set the properties
tb . SetCustomAttribute ( new CustomAttributeBuilder ( type . GetConstructor ( Type . EmptyTypes ) , new object [ 0 ] ) ) ;
}
}
internal override Annotation Annotation
{
get
{
2006-04-11 18:59:43 +04:00
string annotationAttribute = AttributeHelper . GetAnnotationAttributeType ( type ) ;
if ( annotationAttribute ! = null )
2005-11-01 17:01:42 +03:00
{
2006-04-11 18:59:43 +04:00
return new CompiledAnnotation ( type . Assembly . GetType ( annotationAttribute , true ) ) ;
2005-11-01 17:01:42 +03:00
}
return null ;
}
}
2005-12-07 12:06:32 +03:00
#endif
2003-08-21 14:06:34 +04:00
}
2005-06-01 13:49:30 +04:00
sealed class Whidbey
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
private static readonly object [ ] noargs = new object [ 0 ] ;
private static readonly MethodInfo get_IsGenericTypeDefinition = typeof ( Type ) . GetMethod ( "get_IsGenericTypeDefinition" ) ;
2006-01-23 13:18:44 +03:00
private static readonly MethodInfo get_ContainsGenericParameters = typeof ( Type ) . GetMethod ( "get_ContainsGenericParameters" ) ;
2005-06-01 13:49:30 +04:00
private static readonly MethodInfo get_IsGenericMethodDefinition = typeof ( MethodBase ) . GetMethod ( "get_IsGenericMethodDefinition" ) ;
2005-12-19 18:12:49 +03:00
private static readonly MethodInfo method_MakeGenericType = typeof ( Type ) . GetMethod ( "MakeGenericType" ) ;
2003-08-21 14:06:34 +04:00
2005-06-01 13:49:30 +04:00
internal static bool IsGenericTypeDefinition ( Type type )
2003-10-17 12:08:31 +04:00
{
2005-06-01 13:49:30 +04:00
return get_IsGenericTypeDefinition ! = null & & ( bool ) get_IsGenericTypeDefinition . Invoke ( type , noargs ) ;
2003-10-17 12:08:31 +04:00
}
2006-01-23 13:18:44 +03:00
internal static bool ContainsGenericParameters ( Type type )
{
return get_ContainsGenericParameters ! = null & & ( bool ) get_ContainsGenericParameters . Invoke ( type , noargs ) ;
}
2005-06-01 13:49:30 +04:00
internal static bool IsGenericMethodDefinition ( MethodBase mb )
2004-04-23 18:21:43 +04:00
{
2005-06-01 13:49:30 +04:00
return get_IsGenericMethodDefinition ! = null & & ( bool ) get_IsGenericMethodDefinition . Invoke ( mb , noargs ) ;
2004-04-23 18:21:43 +04:00
}
2005-12-19 18:12:49 +03:00
internal static Type MakeGenericType ( Type type , Type [ ] typeArguments )
{
return ( Type ) method_MakeGenericType . Invoke ( type , new object [ ] { typeArguments } ) ;
}
2003-08-21 14:06:34 +04:00
}
2005-06-01 13:49:30 +04:00
sealed class DotNetTypeWrapper : TypeWrapper
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
private const string NamePrefix = "cli." ;
2005-08-25 13:36:36 +04:00
internal const string DelegateInterfaceSuffix = "$Method" ;
2005-06-01 13:49:30 +04:00
private readonly Type type ;
private TypeWrapper [ ] innerClasses ;
private TypeWrapper outerClass ;
private TypeWrapper [ ] interfaces ;
private static Modifiers GetModifiers ( Type type )
2003-10-17 12:08:31 +04:00
{
2005-06-01 13:49:30 +04:00
Modifiers modifiers = 0 ;
if ( type . IsPublic )
2005-05-23 12:24:07 +04:00
{
2005-06-01 13:49:30 +04:00
modifiers | = Modifiers . Public ;
2003-08-21 14:06:34 +04:00
}
2005-06-01 13:49:30 +04:00
else if ( type . IsNestedPublic )
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
modifiers | = Modifiers . Static ;
if ( IsVisible ( type ) )
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
modifiers | = Modifiers . Public ;
2003-08-21 14:06:34 +04:00
}
}
2005-06-01 13:49:30 +04:00
else if ( type . IsNestedPrivate )
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
modifiers | = Modifiers . Private | Modifiers . Static ;
2003-08-21 14:06:34 +04:00
}
2005-06-01 13:49:30 +04:00
else if ( type . IsNestedFamily | | type . IsNestedFamORAssem )
2004-04-23 18:21:43 +04:00
{
2005-06-01 13:49:30 +04:00
modifiers | = Modifiers . Protected | Modifiers . Static ;
}
else if ( type . IsNestedAssembly | | type . IsNestedFamANDAssem )
{
modifiers | = Modifiers . Static ;
2004-04-23 18:21:43 +04:00
}
2003-08-26 15:24:17 +04:00
2005-06-01 13:49:30 +04:00
if ( type . IsSealed )
{
modifiers | = Modifiers . Final ;
}
else if ( type . IsAbstract ) // we can't be abstract if we're final
{
modifiers | = Modifiers . Abstract ;
}
if ( type . IsInterface )
{
modifiers | = Modifiers . Interface ;
}
return modifiers ;
2003-08-26 15:24:17 +04:00
}
2005-06-01 13:49:30 +04:00
// NOTE when this is called on a remapped type, the "warped" underlying type name is returned.
// E.g. GetName(typeof(object)) returns "cli.System.Object".
internal static string GetName ( Type type )
2003-08-26 15:24:17 +04:00
{
2005-12-07 12:06:32 +03:00
Debug . Assert ( ! type . IsArray & & ! AttributeHelper . IsJavaModule ( type . Module ) ) ;
2003-08-26 15:24:17 +04:00
2006-01-23 13:18:44 +03:00
string name = type . FullName ;
if ( name = = null )
{
// open generic types don't have a full name
return null ;
}
2005-12-07 12:06:32 +03:00
if ( AttributeHelper . IsNoPackagePrefix ( type ) )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
// TODO figure out if this is even required
2006-01-23 13:18:44 +03:00
return name . Replace ( '+' , '$' ) ;
2004-08-17 13:05:21 +04:00
}
2005-06-01 13:49:30 +04:00
2006-01-23 13:18:44 +03:00
return MangleTypeName ( name ) ;
2004-08-17 13:05:21 +04:00
}
2005-06-01 13:49:30 +04:00
private static string MangleTypeName ( string name )
2004-08-17 13:05:21 +04:00
{
2005-06-22 17:02:03 +04:00
System . Text . StringBuilder sb = new System . Text . StringBuilder ( NamePrefix , NamePrefix . Length + name . Length ) ;
int quoteMode = 0 ;
2005-06-27 13:06:57 +04:00
bool escape = false ;
2005-06-22 17:02:03 +04:00
for ( int i = 0 ; i < name . Length ; i + + )
{
char c = name [ i ] ;
2005-06-27 13:06:57 +04:00
if ( c = = '[' & & ! escape )
2005-06-22 17:02:03 +04:00
{
quoteMode + + ;
}
2005-06-27 13:06:57 +04:00
if ( c = = ']' & & ! escape )
2005-06-22 17:02:03 +04:00
{
quoteMode - - ;
}
2005-06-27 13:06:57 +04:00
if ( c = = '+' & & ! escape & & ( sb . Length = = 0 | | sb [ sb . Length - 1 ] ! = '$' ) )
2005-06-22 17:02:03 +04:00
{
sb . Append ( '$' ) ;
}
2005-06-27 13:06:57 +04:00
else if ( "_0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" . IndexOf ( c ) ! = - 1
2005-06-22 17:02:03 +04:00
| | ( c = = '.' & & quoteMode = = 0 ) )
{
sb . Append ( c ) ;
}
else
{
2005-06-27 13:06:57 +04:00
sb . Append ( "$$" ) ;
2005-06-22 17:02:03 +04:00
sb . Append ( string . Format ( "{0:X4}" , ( int ) c ) ) ;
}
2005-06-27 13:06:57 +04:00
if ( c = = '\\' )
{
escape = ! escape ;
}
else
{
escape = false ;
}
2005-06-22 17:02:03 +04:00
}
return sb . ToString ( ) ;
2004-08-17 13:05:21 +04:00
}
2005-06-22 17:02:03 +04:00
// NOTE if the name is not a valid mangled type name, no demangling is done and the
// original string is returned
2005-06-01 13:49:30 +04:00
private static string DemangleTypeName ( string name )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
Debug . Assert ( name . StartsWith ( NamePrefix ) ) ;
2005-06-22 17:02:03 +04:00
System . Text . StringBuilder sb = new System . Text . StringBuilder ( name . Length - NamePrefix . Length ) ;
int end = name . Length ;
bool hasDelegateSuffix = name . EndsWith ( DelegateInterfaceSuffix ) ;
if ( hasDelegateSuffix )
2005-06-01 13:49:30 +04:00
{
2005-06-22 17:02:03 +04:00
end - = DelegateInterfaceSuffix . Length ;
}
// TODO we should enforce canonical form
for ( int i = NamePrefix . Length ; i < end ; i + + )
{
char c = name [ i ] ;
if ( c = = '$' )
{
2005-06-27 13:06:57 +04:00
if ( i + 1 < end & & name [ i + 1 ] ! = '$' )
2005-06-22 17:02:03 +04:00
{
2005-06-27 13:06:57 +04:00
sb . Append ( '+' ) ;
2005-06-22 17:02:03 +04:00
}
2005-06-27 13:06:57 +04:00
else
2005-06-22 17:02:03 +04:00
{
2005-06-27 13:06:57 +04:00
i + + ;
if ( i + 5 > end )
{
return name ;
}
int digit0 = "0123456789ABCDEF" . IndexOf ( name [ + + i ] ) ;
int digit1 = "0123456789ABCDEF" . IndexOf ( name [ + + i ] ) ;
int digit2 = "0123456789ABCDEF" . IndexOf ( name [ + + i ] ) ;
int digit3 = "0123456789ABCDEF" . IndexOf ( name [ + + i ] ) ;
if ( digit0 = = - 1 | | digit1 = = - 1 | | digit2 = = - 1 | | digit3 = = - 1 )
{
return name ;
}
sb . Append ( ( char ) ( ( digit0 < < 12 ) + ( digit1 < < 8 ) + ( digit2 < < 4 ) + digit3 ) ) ;
2005-06-22 17:02:03 +04:00
}
}
else
{
sb . Append ( c ) ;
}
}
if ( hasDelegateSuffix )
{
sb . Append ( DelegateInterfaceSuffix ) ;
2005-06-01 13:49:30 +04:00
}
2005-06-22 17:02:03 +04:00
return sb . ToString ( ) ;
2004-08-17 13:05:21 +04:00
}
2005-06-01 13:49:30 +04:00
// this method returns a new TypeWrapper instance for each invocation (doesn't prevent duplicates)
// the caller is responsible for making sure that only one TypeWrapper with the specified name escapes
// out into the world
internal static TypeWrapper CreateDotNetTypeWrapper ( string name )
2004-08-17 13:05:21 +04:00
{
2005-06-22 18:24:16 +04:00
string origname = name ;
2005-06-01 13:49:30 +04:00
bool prefixed = name . StartsWith ( NamePrefix ) ;
if ( prefixed )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
name = DemangleTypeName ( name ) ;
2004-08-17 13:05:21 +04:00
}
2005-06-01 13:49:30 +04:00
Type type = LoadTypeFromLoadedAssemblies ( name ) ;
if ( type ! = null )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
// SECURITY we never expose types from IKVM.Runtime, because doing so would lead to a security hole,
// since the reflection implementation lives inside this assembly, all internal members would
// be accessible through Java reflection.
if ( type . Assembly = = typeof ( DotNetTypeWrapper ) . Assembly )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
return null ;
2004-08-17 13:05:21 +04:00
}
2006-01-23 13:18:44 +03:00
if ( Whidbey . ContainsGenericParameters ( type ) )
2003-08-26 15:24:17 +04:00
{
2005-06-01 13:49:30 +04:00
return null ;
}
2005-12-07 12:06:32 +03:00
if ( prefixed | | AttributeHelper . IsNoPackagePrefix ( type ) )
2005-06-01 13:49:30 +04:00
{
return new DotNetTypeWrapper ( type ) ;
2003-08-26 15:24:17 +04:00
}
}
2005-12-07 12:06:32 +03:00
#if ! COMPACT_FRAMEWORK
2005-06-01 13:49:30 +04:00
if ( name . EndsWith ( DelegateInterfaceSuffix ) )
2003-08-26 15:24:17 +04:00
{
2005-06-01 13:49:30 +04:00
Type delegateType = LoadTypeFromLoadedAssemblies ( name . Substring ( 0 , name . Length - DelegateInterfaceSuffix . Length ) ) ;
if ( delegateType ! = null & & IsDelegate ( delegateType ) )
2003-08-26 15:24:17 +04:00
{
2005-12-07 12:06:32 +03:00
if ( prefixed | | AttributeHelper . IsNoPackagePrefix ( delegateType ) )
2003-08-26 15:24:17 +04:00
{
2005-08-25 13:36:36 +04:00
MethodInfo invoke = delegateType . GetMethod ( "Invoke" ) ;
ParameterInfo [ ] parameters = invoke . GetParameters ( ) ;
Type [ ] args = new Type [ parameters . Length ] ;
for ( int i = 0 ; i < args . Length ; i + + )
{
// we know there aren't any unsupported parameter types, because IsDelegate() returned true
args [ i ] = parameters [ i ] . ParameterType ;
}
2006-02-22 17:44:07 +03:00
// HACK this is an ugly hack to obtain the global ModuleBuilder
ModuleBuilder moduleBuilder = new DynamicClassLoader ( null ) . ModuleBuilder ;
2005-08-25 13:36:36 +04:00
TypeBuilder typeBuilder = moduleBuilder . DefineType ( origname . Substring ( NamePrefix . Length ) , TypeAttributes . NotPublic | TypeAttributes . Interface | TypeAttributes . Abstract ) ;
AttributeHelper . HideFromJava ( typeBuilder ) ;
2006-04-05 12:18:58 +04:00
AttributeHelper . SetModifiers ( typeBuilder , Modifiers . Public | Modifiers . Interface | Modifiers . Abstract , false ) ;
2005-08-25 13:36:36 +04:00
typeBuilder . DefineMethod ( "Invoke" , MethodAttributes . Public | MethodAttributes . Abstract | MethodAttributes . Virtual , CallingConventions . Standard , invoke . ReturnType , args ) ;
return CompiledTypeWrapper . newInstance ( origname , typeBuilder . CreateType ( ) ) ;
2003-08-26 15:24:17 +04:00
}
}
}
2005-12-07 12:06:32 +03:00
#endif
2005-06-01 13:49:30 +04:00
return null ;
2004-06-25 13:38:07 +04:00
}
2005-12-19 18:12:49 +03:00
private static string [ ] ParseGenericArgs ( string args )
{
if ( args [ 0 ] ! = '[' )
throw new NotSupportedException ( ) ;
ArrayList list = new ArrayList ( ) ;
int start = 1 ;
int depth = 1 ;
for ( int i = 1 ; i < args . Length ; i + + )
{
if ( args [ i ] = = '[' )
{
depth + + ;
if ( depth = = 1 )
{
start = i + 1 ;
}
}
else if ( args [ i ] = = ']' )
{
depth - - ;
if ( depth = = 0 )
{
list . Add ( args . Substring ( start , i - start ) ) ;
}
}
}
return ( string [ ] ) list . ToArray ( typeof ( string ) ) ;
}
2005-06-01 13:49:30 +04:00
private static Type LoadTypeFromLoadedAssemblies ( string name )
2004-06-25 13:38:07 +04:00
{
2005-12-19 18:12:49 +03:00
// HACK handle generic types here
int index = name . IndexOf ( "[[" ) ;
if ( index > 0 )
{
int lastIndex = name . LastIndexOf ( "]]" ) ;
if ( lastIndex = = - 1 | | ( lastIndex + 2 < name . Length & & name [ lastIndex + 2 ] ! = ',' ) )
{
return null ;
}
Type t = LoadTypeFromLoadedAssemblies ( name . Substring ( 0 , index ) ) ;
if ( t ! = null & & Whidbey . IsGenericTypeDefinition ( t ) )
{
string [ ] typeArgStrings = ParseGenericArgs ( name . Substring ( index + 1 , lastIndex - index ) ) ;
Type [ ] typeArgs = new Type [ typeArgStrings . Length ] ;
for ( int i = 0 ; i < typeArgs . Length ; i + + )
{
typeArgs [ i ] = LoadTypeFromLoadedAssemblies ( typeArgStrings [ i ] ) ;
if ( typeArgs [ i ] = = null )
{
return null ;
}
}
return Whidbey . MakeGenericType ( t , typeArgs ) ;
}
}
// HACK we ignore the assembly name (we have to do that to make the generic type arguments work)
int comma = name . IndexOf ( ',' ) ;
if ( comma > = 0 )
{
name = name . Substring ( 0 , comma ) ;
}
2005-12-07 12:06:32 +03:00
#if WHIDBEY
2005-12-19 18:12:49 +03:00
if ( JVM . IsStaticCompiler | | JVM . IsIkvmStub )
2005-12-07 12:06:32 +03:00
{
foreach ( Assembly a in AppDomain . CurrentDomain . ReflectionOnlyGetAssemblies ( ) )
{
if ( ! ( a is AssemblyBuilder ) )
{
Type t = a . GetType ( name ) ;
if ( t ! = null
& & ! AttributeHelper . IsJavaModule ( t . Module ) )
{
return t ;
}
// HACK we might be looking for an inner classes
// (if we remove the mangling of NoPackagePrefix types from GetName, we don't need this anymore)
t = a . GetType ( name . Replace ( '$' , '+' ) ) ;
if ( t ! = null
& & ! AttributeHelper . IsJavaModule ( t . Module ) )
{
return t ;
}
}
}
2005-12-19 18:12:49 +03:00
return Type . GetType ( name ) ;
2005-12-07 12:06:32 +03:00
}
#endif
2005-06-01 13:49:30 +04:00
foreach ( Assembly a in AppDomain . CurrentDomain . GetAssemblies ( ) )
{
if ( ! ( a is AssemblyBuilder ) )
{
Type t = a . GetType ( name ) ;
2005-08-25 13:36:36 +04:00
if ( t ! = null
2005-12-07 12:06:32 +03:00
& & ! AttributeHelper . IsJavaModule ( t . Module ) )
2005-06-01 13:49:30 +04:00
{
return t ;
}
// HACK we might be looking for an inner classes
// (if we remove the mangling of NoPackagePrefix types from GetName, we don't need this anymore)
t = a . GetType ( name . Replace ( '$' , '+' ) ) ;
2005-08-25 13:36:36 +04:00
if ( t ! = null
2005-12-07 12:06:32 +03:00
& & ! AttributeHelper . IsJavaModule ( t . Module ) )
2005-06-01 13:49:30 +04:00
{
return t ;
}
}
}
return null ;
2004-06-25 13:38:07 +04:00
}
2005-06-01 13:49:30 +04:00
internal static TypeWrapper GetWrapperFromDotNetType ( Type type )
2004-10-04 23:30:53 +04:00
{
2005-06-01 13:49:30 +04:00
// TODO there should be a better way
return ClassLoaderWrapper . GetBootstrapClassLoader ( ) . LoadClassByDottedName ( DotNetTypeWrapper . GetName ( type ) ) ;
2004-10-04 23:30:53 +04:00
}
2005-06-01 13:49:30 +04:00
private static TypeWrapper GetBaseTypeWrapper ( Type type )
2004-10-04 23:30:53 +04:00
{
2005-06-01 13:49:30 +04:00
if ( type . IsInterface )
2004-12-21 13:26:51 +03:00
{
2005-06-01 13:49:30 +04:00
return null ;
2004-12-21 13:26:51 +03:00
}
2005-06-01 13:49:30 +04:00
else if ( ClassLoaderWrapper . IsRemappedType ( type ) )
2004-12-21 13:26:51 +03:00
{
2005-06-01 13:49:30 +04:00
// Remapped types extend their alter ego
// (e.g. cli.System.Object must appear to be derived from java.lang.Object)
// except when they're sealed, of course.
if ( type . IsSealed )
{
return CoreClasses . java . lang . Object . Wrapper ;
}
return ClassLoaderWrapper . GetWrapperFromType ( type ) ;
2004-12-21 13:26:51 +03:00
}
2005-06-01 13:49:30 +04:00
else if ( ClassLoaderWrapper . IsRemappedType ( type . BaseType ) )
2004-12-21 13:26:51 +03:00
{
2005-06-01 13:49:30 +04:00
return GetWrapperFromDotNetType ( type . BaseType ) ;
2004-12-21 13:26:51 +03:00
}
2005-06-01 13:49:30 +04:00
else
2004-12-21 13:26:51 +03:00
{
2005-06-01 13:49:30 +04:00
return ClassLoaderWrapper . GetWrapperFromType ( type . BaseType ) ;
2004-12-21 13:26:51 +03:00
}
2004-10-04 23:30:53 +04:00
}
2005-06-01 13:49:30 +04:00
internal DotNetTypeWrapper ( Type type )
2006-03-23 14:57:41 +03:00
: base ( GetModifiers ( type ) , GetName ( type ) , GetBaseTypeWrapper ( type ) )
2004-06-25 13:38:07 +04:00
{
2005-06-01 13:49:30 +04:00
Debug . Assert ( ! ( type . IsByRef ) , type . FullName ) ;
Debug . Assert ( ! ( type . IsPointer ) , type . FullName ) ;
Debug . Assert ( ! ( type . IsArray ) , type . FullName ) ;
Debug . Assert ( ! ( type is TypeBuilder ) , type . FullName ) ;
2005-12-07 12:06:32 +03:00
Debug . Assert ( ! ( AttributeHelper . IsJavaModule ( type . Module ) ) ) ;
2005-06-01 13:49:30 +04:00
this . type = type ;
2004-06-25 13:38:07 +04:00
}
2005-06-01 13:49:30 +04:00
internal override ClassLoaderWrapper GetClassLoader ( )
2004-06-25 13:38:07 +04:00
{
2005-06-01 13:49:30 +04:00
return ClassLoaderWrapper . GetSystemClassLoader ( ) ;
2004-06-25 13:38:07 +04:00
}
2005-11-01 17:01:42 +03:00
internal override TypeWrapper MakeArrayType ( int rank )
{
Debug . Assert ( rank ! = 0 ) ;
// NOTE this call to LoadClassByDottedNameFast can never fail and will not trigger a class load
return ClassLoaderWrapper . GetBootstrapClassLoader ( ) . LoadClassByDottedNameFast ( new String ( '[' , rank ) + this . SigName ) ;
}
2005-06-01 13:49:30 +04:00
private class DelegateMethodWrapper : MethodWrapper
2004-06-25 13:38:07 +04:00
{
2005-06-01 13:49:30 +04:00
private ConstructorInfo delegateConstructor ;
private MethodInfo method ;
internal DelegateMethodWrapper ( TypeWrapper declaringType , Type delegateType , TypeWrapper iface )
: base ( declaringType , "<init>" , "(" + iface . SigName + ")V" , null , PrimitiveTypeWrapper . VOID , new TypeWrapper [ ] { iface } , Modifiers . Public , MemberFlags . None )
2004-12-21 13:26:51 +03:00
{
2005-06-01 13:49:30 +04:00
this . delegateConstructor = delegateType . GetConstructor ( new Type [ ] { typeof ( object ) , typeof ( IntPtr ) } ) ;
this . method = iface . TypeAsTBD . GetMethod ( "Invoke" ) ;
2004-12-21 13:26:51 +03:00
}
2005-06-01 13:49:30 +04:00
2005-12-07 12:06:32 +03:00
#if ! COMPACT_FRAMEWORK
2005-06-01 13:49:30 +04:00
internal override void EmitNewobj ( ILGenerator ilgen )
2004-12-21 13:26:51 +03:00
{
2005-06-01 13:49:30 +04:00
ilgen . Emit ( OpCodes . Dup ) ;
ilgen . Emit ( OpCodes . Ldvirtftn , method ) ;
ilgen . Emit ( OpCodes . Newobj , delegateConstructor ) ;
2004-12-21 13:26:51 +03:00
}
2005-12-07 12:06:32 +03:00
#endif
2005-06-01 13:49:30 +04:00
2006-04-10 13:09:09 +04:00
#if ! STATIC_COMPILER
2005-06-01 13:49:30 +04:00
[HideFromJava]
internal override object Invoke ( object obj , object [ ] args , bool nonVirtual )
2004-12-21 13:26:51 +03:00
{
2005-06-01 13:49:30 +04:00
// TODO map exceptions
return Delegate . CreateDelegate ( DeclaringType . TypeAsTBD , args [ 0 ] , "Invoke" ) ;
2004-12-21 13:26:51 +03:00
}
2006-04-10 13:09:09 +04:00
#endif // !STATIC_COMPILER
2005-06-01 13:49:30 +04:00
}
private class ByRefMethodWrapper : SmartMethodWrapper
{
private bool [ ] byrefs ;
private Type [ ] args ;
internal ByRefMethodWrapper ( Type [ ] args , bool [ ] byrefs , TypeWrapper declaringType , string name , string sig , MethodBase method , TypeWrapper returnType , TypeWrapper [ ] parameterTypes , Modifiers modifiers , bool hideFromReflection )
: base ( declaringType , name , sig , method , returnType , parameterTypes , modifiers , hideFromReflection ? MemberFlags . HideFromReflection : MemberFlags . None )
2004-12-21 13:26:51 +03:00
{
2005-06-01 13:49:30 +04:00
this . args = args ;
this . byrefs = byrefs ;
2004-12-21 13:26:51 +03:00
}
2005-06-01 13:49:30 +04:00
2005-12-07 12:06:32 +03:00
#if ! COMPACT_FRAMEWORK
2005-06-01 13:49:30 +04:00
protected override void CallImpl ( ILGenerator ilgen )
2004-06-25 13:38:07 +04:00
{
2005-06-01 13:49:30 +04:00
MethodBase mb = GetMethod ( ) ;
MethodInfo mi = mb as MethodInfo ;
if ( mi ! = null )
{
ilgen . Emit ( OpCodes . Call , mi ) ;
}
else
{
ilgen . Emit ( OpCodes . Call , ( ConstructorInfo ) mb ) ;
}
2004-06-25 13:38:07 +04:00
}
2005-06-01 13:49:30 +04:00
protected override void CallvirtImpl ( ILGenerator ilgen )
2004-12-21 13:26:51 +03:00
{
2005-06-01 13:49:30 +04:00
ilgen . Emit ( OpCodes . Callvirt , ( MethodInfo ) GetMethod ( ) ) ;
2004-12-21 13:26:51 +03:00
}
2005-06-01 13:49:30 +04:00
protected override void NewobjImpl ( ILGenerator ilgen )
2004-06-25 13:38:07 +04:00
{
2005-06-01 13:49:30 +04:00
ilgen . Emit ( OpCodes . Newobj , ( ConstructorInfo ) GetMethod ( ) ) ;
2004-06-25 13:38:07 +04:00
}
2004-12-21 13:26:51 +03:00
2005-06-01 13:49:30 +04:00
protected override void PreEmit ( ILGenerator ilgen )
{
LocalBuilder [ ] locals = new LocalBuilder [ args . Length ] ;
for ( int i = args . Length - 1 ; i > = 0 ; i - - )
{
Type type = args [ i ] ;
if ( type . IsByRef )
{
type = type . Assembly . GetType ( type . GetElementType ( ) . FullName + "[]" , true ) ;
}
locals [ i ] = ilgen . DeclareLocal ( type ) ;
ilgen . Emit ( OpCodes . Stloc , locals [ i ] ) ;
}
for ( int i = 0 ; i < args . Length ; i + + )
{
ilgen . Emit ( OpCodes . Ldloc , locals [ i ] ) ;
if ( args [ i ] . IsByRef )
{
ilgen . Emit ( OpCodes . Ldc_I4_0 ) ;
ilgen . Emit ( OpCodes . Ldelema , args [ i ] . GetElementType ( ) ) ;
}
}
base . PreEmit ( ilgen ) ;
}
2005-12-07 12:06:32 +03:00
#endif
2004-06-25 13:38:07 +04:00
2006-04-10 13:09:09 +04:00
#if ! STATIC_COMPILER
2005-06-01 13:49:30 +04:00
[HideFromJava]
internal override object Invoke ( object obj , object [ ] args , bool nonVirtual )
{
object [ ] newargs = ( object [ ] ) args . Clone ( ) ;
for ( int i = 0 ; i < newargs . Length ; i + + )
{
if ( byrefs [ i ] )
{
newargs [ i ] = ( ( Array ) args [ i ] ) . GetValue ( 0 ) ;
}
}
try
{
return base . Invoke ( obj , newargs , nonVirtual ) ;
}
finally
{
for ( int i = 0 ; i < newargs . Length ; i + + )
{
if ( byrefs [ i ] )
{
( ( Array ) args [ i ] ) . SetValue ( newargs [ i ] , 0 ) ;
}
}
}
}
2006-04-10 13:09:09 +04:00
#endif // !STATIC_COMPILER
2004-08-17 13:05:21 +04:00
}
2005-06-01 13:49:30 +04:00
internal static bool IsVisible ( Type type )
2004-10-19 17:43:55 +04:00
{
2005-06-01 13:49:30 +04:00
return type . IsPublic | | ( type . IsNestedPublic & & IsVisible ( type . DeclaringType ) ) ;
2004-10-19 17:43:55 +04:00
}
2005-06-01 13:49:30 +04:00
private class EnumWrapMethodWrapper : MethodWrapper
2004-10-19 17:43:55 +04:00
{
2005-06-01 13:49:30 +04:00
internal EnumWrapMethodWrapper ( DotNetTypeWrapper tw , TypeWrapper fieldType )
: base ( tw , "wrap" , "(" + fieldType . SigName + ")" + tw . SigName , null , tw , new TypeWrapper [ ] { fieldType } , Modifiers . Static | Modifiers . Public , MemberFlags . None )
{
}
2004-10-19 17:43:55 +04:00
2005-12-07 12:06:32 +03:00
#if ! COMPACT_FRAMEWORK
2005-06-01 13:49:30 +04:00
internal override void EmitCall ( ILGenerator ilgen )
{
// We don't actually need to do anything here!
// The compiler will insert a boxing operation after calling us and that will
// result in our argument being boxed (since that's still sitting on the stack).
}
2005-12-07 12:06:32 +03:00
#endif
2005-06-01 13:49:30 +04:00
2006-04-10 13:09:09 +04:00
#if ! STATIC_COMPILER
2005-06-01 13:49:30 +04:00
[HideFromJava]
internal override object Invoke ( object obj , object [ ] args , bool nonVirtual )
2004-10-19 17:43:55 +04:00
{
2005-06-01 13:49:30 +04:00
return Enum . ToObject ( DeclaringType . TypeAsTBD , ( ( IConvertible ) args [ 0 ] ) . ToInt64 ( null ) ) ;
2004-10-19 17:43:55 +04:00
}
2006-04-10 13:09:09 +04:00
#endif // !STATIC_COMPILER
2004-10-19 17:43:55 +04:00
}
2005-06-01 13:49:30 +04:00
internal class EnumValueFieldWrapper : FieldWrapper
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
// NOTE if the reference on the stack is null, we *want* the NullReferenceException, so we don't use TypeWrapper.EmitUnbox
internal EnumValueFieldWrapper ( DotNetTypeWrapper tw , TypeWrapper fieldType )
2006-04-05 12:18:58 +04:00
: base ( tw , fieldType , "Value" , fieldType . SigName , new ExModifiers ( Modifiers . Public | Modifiers . Final , false ) , null )
2004-12-21 13:26:51 +03:00
{
}
2005-06-01 13:49:30 +04:00
2005-12-07 12:06:32 +03:00
#if ! COMPACT_FRAMEWORK
2005-06-01 13:49:30 +04:00
protected override void EmitGetImpl ( ILGenerator ilgen )
2004-12-21 13:26:51 +03:00
{
2005-06-01 13:49:30 +04:00
DotNetTypeWrapper tw = ( DotNetTypeWrapper ) this . DeclaringType ;
2005-12-20 15:44:29 +03:00
if ( ilgen . IsBoxPending ( tw . type ) )
2005-06-01 13:49:30 +04:00
{
2005-12-20 15:44:29 +03:00
ilgen . ClearPendingBox ( ) ;
2005-06-01 13:49:30 +04:00
}
2005-12-20 15:44:29 +03:00
else
2005-06-01 13:49:30 +04:00
{
2005-12-20 15:44:29 +03:00
ilgen . Emit ( OpCodes . Unbox , tw . type ) ;
// FXBUG the .NET 1.1 verifier doesn't understand that ldobj on an enum that has an underlying type
// of byte or short that the resulting type on the stack is an int32, so we have to
// to it the hard way. Note that this is fixed in Whidbey.
Type underlyingType = Enum . GetUnderlyingType ( tw . type ) ;
if ( underlyingType = = typeof ( sbyte ) | | underlyingType = = typeof ( byte ) )
{
ilgen . Emit ( OpCodes . Ldind_I1 ) ;
}
else if ( underlyingType = = typeof ( short ) | | underlyingType = = typeof ( ushort ) )
{
ilgen . Emit ( OpCodes . Ldind_I2 ) ;
}
else if ( underlyingType = = typeof ( int ) | | underlyingType = = typeof ( uint ) )
{
ilgen . Emit ( OpCodes . Ldind_I4 ) ;
}
else if ( underlyingType = = typeof ( long ) | | underlyingType = = typeof ( ulong ) )
{
ilgen . Emit ( OpCodes . Ldind_I8 ) ;
}
2005-06-01 13:49:30 +04:00
}
2004-12-21 13:26:51 +03:00
}
2005-06-01 13:49:30 +04:00
protected override void EmitSetImpl ( ILGenerator ilgen )
2004-12-21 13:26:51 +03:00
{
2005-06-01 13:49:30 +04:00
throw new InvalidOperationException ( ) ;
2004-12-21 13:26:51 +03:00
}
2005-12-07 12:06:32 +03:00
#endif
2005-06-01 13:49:30 +04:00
2006-04-10 13:09:09 +04:00
#if ! STATIC_COMPILER
2005-06-01 13:49:30 +04:00
internal override void SetValue ( object obj , object val )
2004-12-21 13:26:51 +03:00
{
2005-06-01 13:49:30 +04:00
// NOTE even though the field is final, JNI reflection can still be used to set its value!
// NOTE the CLI spec says that an enum has exactly one instance field, so we take advantage of that fact.
FieldInfo f = DeclaringType . TypeAsTBD . GetFields ( BindingFlags . Public | BindingFlags . NonPublic | BindingFlags . Instance ) [ 0 ] ;
f . SetValue ( obj , val ) ;
2004-12-21 13:26:51 +03:00
}
2006-04-10 13:09:09 +04:00
#endif // !STATIC_COMPILER
2005-06-01 13:49:30 +04:00
// this method takes a boxed Enum and returns its value as a boxed primitive
// of the subset of Java primitives (i.e. byte, short, int, long)
internal static object GetEnumPrimitiveValue ( object obj )
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
Type underlyingType = Enum . GetUnderlyingType ( obj . GetType ( ) ) ;
if ( underlyingType = = typeof ( sbyte ) | | underlyingType = = typeof ( byte ) )
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
return unchecked ( ( byte ) ( ( IConvertible ) obj ) . ToInt32 ( null ) ) ;
2003-08-21 14:06:34 +04:00
}
2005-06-01 13:49:30 +04:00
else if ( underlyingType = = typeof ( short ) | | underlyingType = = typeof ( ushort ) )
{
return unchecked ( ( short ) ( ( IConvertible ) obj ) . ToInt32 ( null ) ) ;
}
else if ( underlyingType = = typeof ( int ) )
{
return ( ( IConvertible ) obj ) . ToInt32 ( null ) ;
}
else if ( underlyingType = = typeof ( uint ) )
{
return unchecked ( ( int ) ( ( IConvertible ) obj ) . ToUInt32 ( null ) ) ;
}
else if ( underlyingType = = typeof ( long ) )
{
return ( ( IConvertible ) obj ) . ToInt64 ( null ) ;
}
else if ( underlyingType = = typeof ( ulong ) )
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
return unchecked ( ( long ) ( ( IConvertible ) obj ) . ToUInt64 ( null ) ) ;
2003-08-21 14:06:34 +04:00
}
else
{
2005-06-01 13:49:30 +04:00
throw new InvalidOperationException ( ) ;
2003-08-21 14:06:34 +04:00
}
}
2006-04-10 13:09:09 +04:00
#if ! STATIC_COMPILER
2005-06-01 13:49:30 +04:00
internal override object GetValue ( object obj )
{
return GetEnumPrimitiveValue ( obj ) ;
}
2006-04-10 13:09:09 +04:00
#endif // !STATIC_COMPILER
2005-06-01 13:49:30 +04:00
}
internal override Assembly Assembly
{
get
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
return type . Assembly ;
2003-08-21 14:06:34 +04:00
}
2005-06-01 13:49:30 +04:00
}
2003-08-21 14:06:34 +04:00
2005-06-01 13:49:30 +04:00
private class ValueTypeDefaultCtor : MethodWrapper
{
internal ValueTypeDefaultCtor ( DotNetTypeWrapper tw )
: base ( tw , "<init>" , "()V" , null , PrimitiveTypeWrapper . VOID , TypeWrapper . EmptyArray , Modifiers . Public , MemberFlags . None )
{
}
2004-10-19 17:43:55 +04:00
2005-12-07 12:06:32 +03:00
#if ! COMPACT_FRAMEWORK
2005-06-01 13:49:30 +04:00
internal override void EmitNewobj ( ILGenerator ilgen )
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
LocalBuilder local = ilgen . DeclareLocal ( DeclaringType . TypeAsTBD ) ;
ilgen . Emit ( OpCodes . Ldloc , local ) ;
ilgen . Emit ( OpCodes . Box , DeclaringType . TypeAsTBD ) ;
}
2005-12-07 12:06:32 +03:00
#endif
2005-06-01 13:49:30 +04:00
2006-04-10 13:09:09 +04:00
#if ! STATIC_COMPILER
2005-06-01 13:49:30 +04:00
[HideFromJava]
internal override object Invoke ( object obj , object [ ] args , bool nonVirtual )
{
if ( obj = = null )
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
obj = Activator . CreateInstance ( DeclaringType . TypeAsTBD ) ;
2003-08-21 14:06:34 +04:00
}
2005-06-01 13:49:30 +04:00
return obj ;
2003-08-21 14:06:34 +04:00
}
2006-04-10 13:09:09 +04:00
#endif // !STATIC_COMPILER
2005-06-01 13:49:30 +04:00
}
2003-08-21 14:06:34 +04:00
2005-06-01 13:49:30 +04:00
protected override void LazyPublishMembers ( )
{
ArrayList fieldsList = new ArrayList ( ) ;
ArrayList methodsList = new ArrayList ( ) ;
// special support for enums
if ( type . IsEnum )
2004-10-19 17:43:55 +04:00
{
2005-06-01 13:49:30 +04:00
Type underlyingType = Enum . GetUnderlyingType ( type ) ;
if ( underlyingType = = typeof ( sbyte ) )
{
underlyingType = typeof ( byte ) ;
}
else if ( underlyingType = = typeof ( ushort ) )
{
underlyingType = typeof ( short ) ;
}
else if ( underlyingType = = typeof ( uint ) )
{
underlyingType = typeof ( int ) ;
}
else if ( underlyingType = = typeof ( ulong ) )
{
underlyingType = typeof ( long ) ;
}
TypeWrapper fieldType = ClassLoaderWrapper . GetWrapperFromType ( underlyingType ) ;
FieldInfo [ ] fields = type . GetFields ( BindingFlags . DeclaredOnly | BindingFlags . Public | BindingFlags . Static ) ;
for ( int i = 0 ; i < fields . Length ; i + + )
{
if ( fields [ i ] . FieldType = = type )
{
string name = fields [ i ] . Name ;
if ( name = = "Value" )
{
name = "_Value" ;
}
else if ( name . StartsWith ( "_" ) & & name . EndsWith ( "Value" ) )
{
name = "_" + name ;
}
2005-12-07 12:06:32 +03:00
#if WHIDBEY
object val = fields [ i ] . GetRawConstantValue ( ) ;
#else
2005-06-01 13:49:30 +04:00
object val = EnumValueFieldWrapper . GetEnumPrimitiveValue ( fields [ i ] . GetValue ( null ) ) ;
2005-12-07 12:06:32 +03:00
#endif
2005-08-14 19:49:50 +04:00
fieldsList . Add ( new ConstantFieldWrapper ( this , fieldType , name , fieldType . SigName , Modifiers . Public | Modifiers . Static | Modifiers . Final , fields [ i ] , val , MemberFlags . LiteralField ) ) ;
2005-06-01 13:49:30 +04:00
}
}
fieldsList . Add ( new EnumValueFieldWrapper ( this , fieldType ) ) ;
methodsList . Add ( new EnumWrapMethodWrapper ( this , fieldType ) ) ;
2004-10-19 17:43:55 +04:00
}
2005-06-01 13:49:30 +04:00
else
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
FieldInfo [ ] fields = type . GetFields ( BindingFlags . DeclaredOnly | BindingFlags . Public | BindingFlags . NonPublic | BindingFlags . Static | BindingFlags . Instance ) ;
for ( int i = 0 ; i < fields . Length ; i + + )
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
// TODO for remapped types, instance fields need to be converted to static getter/setter methods
if ( fields [ i ] . FieldType . IsPointer )
{
// skip, pointer fields are not supported
}
else
{
// TODO handle name/signature clash
2006-04-05 12:18:58 +04:00
fieldsList . Add ( CreateFieldWrapperDotNet ( AttributeHelper . GetModifiers ( fields [ i ] , true ) . Modifiers , fields [ i ] . Name , fields [ i ] . FieldType , fields [ i ] ) ) ;
2005-06-01 13:49:30 +04:00
}
2003-11-17 15:01:50 +03:00
}
2005-06-01 13:49:30 +04:00
// special case for delegate constructors!
if ( IsDelegate ( type ) )
{
TypeWrapper iface = InnerClasses [ 0 ] ;
Debug . Assert ( iface is CompiledTypeWrapper ) ;
iface . Finish ( ) ;
methodsList . Add ( new DelegateMethodWrapper ( this , type , iface ) ) ;
}
bool fabricateDefaultCtor = type . IsValueType ;
ConstructorInfo [ ] constructors = type . GetConstructors ( BindingFlags . DeclaredOnly | BindingFlags . Public | BindingFlags . NonPublic | BindingFlags . Static | BindingFlags . Instance ) ;
for ( int i = 0 ; i < constructors . Length ; i + + )
2003-11-17 15:01:50 +03:00
{
2005-01-03 11:26:21 +03:00
string name ;
string sig ;
2005-06-01 13:49:30 +04:00
if ( MakeMethodDescriptor ( constructors [ i ] , out name , out sig ) )
{
if ( fabricateDefaultCtor & & ! constructors [ i ] . IsStatic & & sig = = "()V" )
{
fabricateDefaultCtor = false ;
}
// TODO handle name/signature clash
methodsList . Add ( CreateMethodWrapper ( name , sig , constructors [ i ] , false ) ) ;
}
}
if ( fabricateDefaultCtor )
{
// Value types have an implicit default ctor
methodsList . Add ( new ValueTypeDefaultCtor ( this ) ) ;
}
MethodInfo [ ] methods = type . GetMethods ( BindingFlags . DeclaredOnly | BindingFlags . Public | BindingFlags . NonPublic | BindingFlags . Static | BindingFlags . Instance ) ;
for ( int i = 0 ; i < methods . Length ; i + + )
{
if ( methods [ i ] . IsStatic & & type . IsInterface )
2003-11-17 15:01:50 +03:00
{
2005-06-01 13:49:30 +04:00
// skip, Java cannot deal with static methods on interfaces
}
else
{
string name ;
string sig ;
if ( MakeMethodDescriptor ( methods [ i ] , out name , out sig ) )
2004-11-04 15:50:28 +03:00
{
2005-06-01 13:49:30 +04:00
if ( ! methods [ i ] . IsStatic & & ! methods [ i ] . IsPrivate & & BaseTypeWrapper ! = null )
2004-11-04 15:50:28 +03:00
{
2005-06-01 13:49:30 +04:00
MethodWrapper baseMethod = BaseTypeWrapper . GetMethodWrapper ( name , sig , true ) ;
if ( baseMethod ! = null & & baseMethod . IsFinal & & ! baseMethod . IsStatic & & ! baseMethod . IsPrivate )
{
continue ;
}
2004-11-04 15:50:28 +03:00
}
2005-06-01 13:49:30 +04:00
// TODO handle name/signature clash
methodsList . Add ( CreateMethodWrapper ( name , sig , methods [ i ] , false ) ) ;
2004-11-04 15:50:28 +03:00
}
2003-12-20 01:19:18 +03:00
}
}
2005-06-01 13:49:30 +04:00
// HACK private interface implementations need to be published as well
// (otherwise the type appears abstract while it isn't)
if ( ! type . IsInterface )
2003-12-20 01:19:18 +03:00
{
2005-06-01 13:49:30 +04:00
Hashtable clash = null ;
Type [ ] interfaces = type . GetInterfaces ( ) ;
for ( int i = 0 ; i < interfaces . Length ; i + + )
2003-12-20 01:19:18 +03:00
{
2005-06-01 13:49:30 +04:00
if ( interfaces [ i ] . IsPublic )
2003-12-20 01:19:18 +03:00
{
2005-06-01 13:49:30 +04:00
InterfaceMapping map = type . GetInterfaceMap ( interfaces [ i ] ) ;
for ( int j = 0 ; j < map . InterfaceMethods . Length ; j + + )
2003-12-20 01:19:18 +03:00
{
2005-06-01 13:49:30 +04:00
if ( ! map . TargetMethods [ j ] . IsPublic & & map . TargetMethods [ j ] . DeclaringType = = type )
2003-12-20 01:19:18 +03:00
{
2005-06-01 13:49:30 +04:00
string name ;
string sig ;
if ( MakeMethodDescriptor ( map . InterfaceMethods [ j ] , out name , out sig ) )
2004-11-04 15:50:28 +03:00
{
2005-06-01 13:49:30 +04:00
if ( BaseTypeWrapper ! = null )
2004-11-04 15:50:28 +03:00
{
2005-06-01 13:49:30 +04:00
MethodWrapper baseMethod = BaseTypeWrapper . GetMethodWrapper ( name , sig , true ) ;
if ( baseMethod ! = null & & ! baseMethod . IsStatic & & baseMethod . IsPublic )
{
continue ;
}
2004-11-04 15:50:28 +03:00
}
2005-06-01 13:49:30 +04:00
if ( clash = = null )
2005-02-02 18:11:26 +03:00
{
2005-06-01 13:49:30 +04:00
clash = new Hashtable ( ) ;
foreach ( MethodWrapper mw in methodsList )
{
clash . Add ( mw . Name + mw . Signature , null ) ;
}
}
if ( ! clash . ContainsKey ( name + sig ) )
{
clash . Add ( name + sig , null ) ;
methodsList . Add ( CreateMethodWrapper ( name , sig , map . InterfaceMethods [ j ] , true ) ) ;
}
2005-02-02 18:11:26 +03:00
}
2003-12-20 01:19:18 +03:00
}
}
}
2003-11-17 15:01:50 +03:00
}
2003-08-21 14:06:34 +04:00
}
2004-04-23 18:21:43 +04:00
2005-06-01 13:49:30 +04:00
// for non-final remapped types, we need to add all the virtual methods in our alter ego (which
// appears as our base class) and make them final (to prevent Java code from overriding these
// methods, which don't really exist).
if ( ClassLoaderWrapper . IsRemappedType ( type ) & & ! type . IsSealed & & ! type . IsInterface )
2004-04-23 18:21:43 +04:00
{
2005-06-01 13:49:30 +04:00
// Finish the type, to make sure the methods are populated
this . BaseTypeWrapper . Finish ( ) ;
Hashtable h = new Hashtable ( ) ;
TypeWrapper baseTypeWrapper = this . BaseTypeWrapper ;
while ( baseTypeWrapper ! = null )
2004-04-23 18:21:43 +04:00
{
2005-06-01 13:49:30 +04:00
foreach ( MethodWrapper m in baseTypeWrapper . GetMethods ( ) )
2004-04-23 18:21:43 +04:00
{
2005-06-01 13:49:30 +04:00
if ( ! m . IsStatic & & ! m . IsFinal & & ( m . IsPublic | | m . IsProtected ) & & m . Name ! = "<init>" )
2004-04-23 18:21:43 +04:00
{
2005-06-01 13:49:30 +04:00
if ( ! h . ContainsKey ( m . Name + m . Signature ) )
{
h . Add ( m . Name + m . Signature , "" ) ;
// TODO handle name/sig clash (what should we do?)
methodsList . Add ( new BaseFinalMethodWrapper ( this , m ) ) ;
}
2004-04-23 18:21:43 +04:00
}
}
2005-06-01 13:49:30 +04:00
baseTypeWrapper = baseTypeWrapper . BaseTypeWrapper ;
}
}
}
SetMethods ( ( MethodWrapper [ ] ) methodsList . ToArray ( typeof ( MethodWrapper ) ) ) ;
SetFields ( ( FieldWrapper [ ] ) fieldsList . ToArray ( typeof ( FieldWrapper ) ) ) ;
2004-08-17 13:05:21 +04:00
}
2005-06-01 13:49:30 +04:00
private class BaseFinalMethodWrapper : MethodWrapper
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
private MethodWrapper m ;
2004-08-17 13:05:21 +04:00
2005-06-01 13:49:30 +04:00
internal BaseFinalMethodWrapper ( DotNetTypeWrapper tw , MethodWrapper m )
: base ( tw , m . Name , m . Signature , m . GetMethod ( ) , m . ReturnType , m . GetParameters ( ) , m . Modifiers | Modifiers . Final , MemberFlags . None )
{
this . m = m ;
}
2004-08-17 13:05:21 +04:00
2005-12-07 12:06:32 +03:00
#if ! COMPACT_FRAMEWORK
2005-06-01 13:49:30 +04:00
internal override void EmitCall ( ILGenerator ilgen )
{
// we direct EmitCall to EmitCallvirt, because we always want to end up at the instancehelper method
// (EmitCall would go to our alter ego .NET type and that wouldn't be legal)
m . EmitCallvirt ( ilgen ) ;
}
2004-08-17 13:05:21 +04:00
2005-06-01 13:49:30 +04:00
internal override void EmitCallvirt ( ILGenerator ilgen )
{
m . EmitCallvirt ( ilgen ) ;
}
2005-12-07 12:06:32 +03:00
#endif
2005-06-01 13:49:30 +04:00
2006-04-10 13:09:09 +04:00
#if ! STATIC_COMPILER
2005-06-01 13:49:30 +04:00
[HideFromJava]
internal override object Invoke ( object obj , object [ ] args , bool nonVirtual )
{
return m . Invoke ( obj , args , nonVirtual ) ;
}
2006-04-10 13:09:09 +04:00
#endif // !STATIC_COMPILER
2004-10-04 23:30:53 +04:00
}
2005-06-01 13:49:30 +04:00
private bool MakeMethodDescriptor ( MethodBase mb , out string name , out string sig )
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
if ( Whidbey . IsGenericMethodDefinition ( mb ) )
2003-08-21 14:06:34 +04:00
{
2005-01-03 11:26:21 +03:00
name = null ;
sig = null ;
return false ;
2003-08-21 14:06:34 +04:00
}
2005-06-01 13:49:30 +04:00
System . Text . StringBuilder sb = new System . Text . StringBuilder ( ) ;
sb . Append ( '(' ) ;
ParameterInfo [ ] parameters = mb . GetParameters ( ) ;
TypeWrapper [ ] args = new TypeWrapper [ parameters . Length ] ;
for ( int i = 0 ; i < parameters . Length ; i + + )
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
Type type = parameters [ i ] . ParameterType ;
if ( type . IsPointer )
2004-10-04 23:30:53 +04:00
{
2005-01-03 11:26:21 +03:00
name = null ;
sig = null ;
return false ;
2004-10-04 23:30:53 +04:00
}
2005-06-01 13:49:30 +04:00
if ( type . IsByRef )
2003-08-26 15:24:17 +04:00
{
2005-06-01 13:49:30 +04:00
if ( type . GetElementType ( ) . IsPointer )
{
name = null ;
sig = null ;
return false ;
}
type = type . Assembly . GetType ( type . GetElementType ( ) . FullName + "[]" , true ) ;
if ( mb . IsAbstract )
{
// Since we cannot override methods with byref arguments, we don't report abstract
// methods with byref args.
name = null ;
sig = null ;
return false ;
}
2003-08-26 15:24:17 +04:00
}
2005-06-01 13:49:30 +04:00
TypeWrapper tw = ClassLoaderWrapper . GetWrapperFromType ( type ) ;
args [ i ] = tw ;
sb . Append ( tw . SigName ) ;
2003-08-21 14:06:34 +04:00
}
2005-06-01 13:49:30 +04:00
sb . Append ( ')' ) ;
if ( mb is ConstructorInfo )
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
TypeWrapper ret = PrimitiveTypeWrapper . VOID ;
if ( mb . IsStatic )
{
name = "<clinit>" ;
}
else
{
name = "<init>" ;
}
sb . Append ( ret . SigName ) ;
sig = sb . ToString ( ) ;
return true ;
2003-08-21 14:06:34 +04:00
}
else
{
2005-06-01 13:49:30 +04:00
Type type = ( ( MethodInfo ) mb ) . ReturnType ;
if ( type . IsPointer | | type . IsByRef )
{
name = null ;
sig = null ;
return false ;
}
TypeWrapper ret = ClassLoaderWrapper . GetWrapperFromType ( type ) ;
sb . Append ( ret . SigName ) ;
name = mb . Name ;
sig = sb . ToString ( ) ;
return true ;
2003-08-21 14:06:34 +04:00
}
}
2005-06-01 13:49:30 +04:00
internal override TypeWrapper [ ] Interfaces
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
get
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
lock ( this )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
if ( interfaces = = null )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
Type [ ] interfaceTypes = type . GetInterfaces ( ) ;
interfaces = new TypeWrapper [ interfaceTypes . Length ] ;
for ( int i = 0 ; i < interfaces . Length ; i + + )
2004-12-02 11:43:05 +03:00
{
2005-06-01 13:49:30 +04:00
if ( interfaceTypes [ i ] . DeclaringType ! = null & &
2005-12-07 12:06:32 +03:00
AttributeHelper . IsHideFromJava ( interfaceTypes [ i ] ) & &
2005-06-01 13:49:30 +04:00
interfaceTypes [ i ] . Name = = "__Interface" )
{
// we have to return the declaring type for ghost interfaces
interfaces [ i ] = ClassLoaderWrapper . GetWrapperFromType ( interfaceTypes [ i ] . DeclaringType ) ;
}
else
{
interfaces [ i ] = ClassLoaderWrapper . GetWrapperFromType ( interfaceTypes [ i ] ) ;
}
2004-12-02 11:43:05 +03:00
}
2004-08-17 13:05:21 +04:00
}
2005-06-01 13:49:30 +04:00
return interfaces ;
2004-08-17 13:05:21 +04:00
}
2003-08-21 14:06:34 +04:00
}
}
2005-06-01 13:49:30 +04:00
private static bool IsDelegate ( Type type )
2004-09-05 13:37:58 +04:00
{
2005-06-01 13:49:30 +04:00
// HACK non-public delegates do not get the special treatment (because they are likely to refer to
// non-public types in the arg list and they're not really useful anyway)
// NOTE we don't have to check in what assembly the type lives, because this is a DotNetTypeWrapper,
// we know that it is a different assembly.
if ( ! type . IsAbstract & & type . IsSubclassOf ( typeof ( MulticastDelegate ) ) & & IsVisible ( type ) )
2005-02-11 17:46:58 +03:00
{
2005-06-01 13:49:30 +04:00
MethodInfo invoke = type . GetMethod ( "Invoke" ) ;
if ( invoke ! = null )
2005-02-11 17:46:58 +03:00
{
2005-06-01 13:49:30 +04:00
foreach ( ParameterInfo p in invoke . GetParameters ( ) )
2005-02-11 17:46:58 +03:00
{
2005-06-01 13:49:30 +04:00
// TODO at the moment we don't support delegates with pointer or byref parameters
if ( p . ParameterType . IsPointer | | p . ParameterType . IsByRef )
{
return false ;
}
2005-02-11 17:46:58 +03:00
}
2005-06-01 13:49:30 +04:00
return true ;
2005-02-11 17:46:58 +03:00
}
}
2005-06-01 13:49:30 +04:00
return false ;
2004-09-05 13:37:58 +04:00
}
2005-06-01 13:49:30 +04:00
internal override TypeWrapper [ ] InnerClasses
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
get
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
lock ( this )
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
if ( innerClasses = = null )
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
if ( IsDelegate ( type ) )
{
innerClasses = new TypeWrapper [ ] { ClassLoaderWrapper . GetBootstrapClassLoader ( ) . LoadClassByDottedName ( Name + DelegateInterfaceSuffix ) } ;
}
else
2004-09-05 13:37:58 +04:00
{
2005-06-01 13:49:30 +04:00
Type [ ] nestedTypes = type . GetNestedTypes ( BindingFlags . Public | BindingFlags . NonPublic ) ;
ArrayList list = new ArrayList ( nestedTypes . Length ) ;
for ( int i = 0 ; i < nestedTypes . Length ; i + + )
2004-10-04 23:30:53 +04:00
{
2005-06-01 13:49:30 +04:00
if ( ! Whidbey . IsGenericTypeDefinition ( nestedTypes [ i ] ) )
{
list . Add ( ClassLoaderWrapper . GetWrapperFromType ( nestedTypes [ i ] ) ) ;
}
2004-10-04 23:30:53 +04:00
}
2005-06-01 13:49:30 +04:00
innerClasses = ( TypeWrapper [ ] ) list . ToArray ( typeof ( TypeWrapper ) ) ;
2004-09-05 13:37:58 +04:00
}
2003-08-21 14:06:34 +04:00
}
}
2005-06-01 13:49:30 +04:00
return innerClasses ;
2003-08-21 14:06:34 +04:00
}
}
2005-06-01 13:49:30 +04:00
internal override TypeWrapper DeclaringTypeWrapper
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
get
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
if ( outerClass = = null )
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
Type outer = type . DeclaringType ;
if ( outer ! = null )
{
outerClass = ClassLoaderWrapper . GetWrapperFromType ( outer ) ;
}
2003-08-21 14:06:34 +04:00
}
2005-06-01 13:49:30 +04:00
return outerClass ;
2003-08-21 14:06:34 +04:00
}
}
2005-06-01 13:49:30 +04:00
internal override Modifiers ReflectiveModifiers
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
get
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
if ( DeclaringTypeWrapper ! = null )
{
return Modifiers | Modifiers . Static ;
}
return Modifiers ;
2003-08-21 14:06:34 +04:00
}
}
2005-06-01 13:49:30 +04:00
private FieldWrapper CreateFieldWrapperDotNet ( Modifiers modifiers , string name , Type fieldType , FieldInfo field )
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
TypeWrapper type = ClassLoaderWrapper . GetWrapperFromType ( fieldType ) ;
if ( field . IsLiteral )
{
2005-08-14 19:49:50 +04:00
return new ConstantFieldWrapper ( this , type , name , type . SigName , modifiers , field , null , MemberFlags . LiteralField ) ;
2005-06-01 13:49:30 +04:00
}
else
{
2006-04-05 12:18:58 +04:00
return FieldWrapper . Create ( this , type , field , name , type . SigName , new ExModifiers ( modifiers , false ) ) ;
2005-06-01 13:49:30 +04:00
}
2003-08-21 14:06:34 +04:00
}
2005-06-01 13:49:30 +04:00
private MethodWrapper CreateMethodWrapper ( string name , string sig , MethodBase mb , bool privateInterfaceImplHack )
2003-08-21 14:06:34 +04:00
{
2006-04-05 12:18:58 +04:00
ExModifiers exmods = AttributeHelper . GetModifiers ( mb , true ) ;
Modifiers mods = exmods . Modifiers ;
2005-06-01 13:49:30 +04:00
if ( name = = "Finalize" & & sig = = "()V" & & ! mb . IsStatic & &
TypeAsBaseType . IsSubclassOf ( CoreClasses . java . lang . Object . Wrapper . TypeAsBaseType ) )
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
// TODO if the .NET also has a "finalize" method, we need to hide that one (or rename it, or whatever)
MethodWrapper mw = new SimpleCallMethodWrapper ( this , "finalize" , "()V" , ( MethodInfo ) mb , null , null , mods , MemberFlags . None , SimpleOpCode . Call , SimpleOpCode . Callvirt ) ;
mw . SetDeclaredExceptions ( new string [ ] { "java.lang.Throwable" } ) ;
return mw ;
}
ParameterInfo [ ] parameters = mb . GetParameters ( ) ;
Type [ ] args = new Type [ parameters . Length ] ;
bool hasByRefArgs = false ;
bool [ ] byrefs = null ;
for ( int i = 0 ; i < parameters . Length ; i + + )
{
args [ i ] = parameters [ i ] . ParameterType ;
if ( parameters [ i ] . ParameterType . IsByRef )
2003-08-26 15:24:17 +04:00
{
2005-06-01 13:49:30 +04:00
if ( byrefs = = null )
{
byrefs = new bool [ args . Length ] ;
}
byrefs [ i ] = true ;
hasByRefArgs = true ;
2003-08-26 15:24:17 +04:00
}
2003-08-21 14:06:34 +04:00
}
2005-06-01 13:49:30 +04:00
if ( privateInterfaceImplHack )
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
mods & = ~ Modifiers . Abstract ;
2004-08-17 13:05:21 +04:00
mods | = Modifiers . Final ;
2003-08-21 14:06:34 +04:00
}
2005-06-01 13:49:30 +04:00
if ( hasByRefArgs )
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
if ( ! ( mb is ConstructorInfo ) & & ! mb . IsStatic )
{
mods | = Modifiers . Final ;
}
2004-08-17 13:05:21 +04:00
// TODO pass in the argument and return types
2005-06-01 13:49:30 +04:00
return new ByRefMethodWrapper ( args , byrefs , this , name , sig , mb , null , null , mods , false ) ;
2003-08-21 14:06:34 +04:00
}
2004-08-17 13:05:21 +04:00
else
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
if ( mb is ConstructorInfo )
{
// TODO pass in the argument and return types
return new SmartConstructorMethodWrapper ( this , name , sig , ( ConstructorInfo ) mb , null , mods , MemberFlags . None ) ;
}
else
{
// TODO pass in the argument and return types
return new SmartCallMethodWrapper ( this , name , sig , ( MethodInfo ) mb , null , null , mods , MemberFlags . None , SimpleOpCode . Call , SimpleOpCode . Callvirt ) ;
}
2003-08-21 14:06:34 +04:00
}
}
2005-06-01 13:49:30 +04:00
internal override Type TypeAsTBD
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
get
{
return type ;
}
2003-08-21 14:06:34 +04:00
}
2004-04-23 18:21:43 +04:00
2005-06-01 13:49:30 +04:00
internal override bool IsRemapped
2004-04-23 18:21:43 +04:00
{
2005-06-01 13:49:30 +04:00
get
{
return ClassLoaderWrapper . IsRemappedType ( type ) ;
}
2004-04-23 18:21:43 +04:00
}
2004-10-19 17:43:55 +04:00
2005-12-07 12:06:32 +03:00
#if ! COMPACT_FRAMEWORK
2005-06-01 13:49:30 +04:00
internal override void EmitInstanceOf ( TypeWrapper context , ILGenerator ilgen )
2004-10-19 17:43:55 +04:00
{
2005-06-01 13:49:30 +04:00
if ( IsRemapped )
2004-10-19 17:43:55 +04:00
{
2005-06-01 13:49:30 +04:00
TypeWrapper shadow = ClassLoaderWrapper . GetWrapperFromTypeFast ( type ) ;
MethodInfo method = shadow . TypeAsBaseType . GetMethod ( "__<instanceof>" ) ;
if ( method ! = null )
{
ilgen . Emit ( OpCodes . Call , method ) ;
return ;
}
2004-10-19 17:43:55 +04:00
}
2005-06-01 13:49:30 +04:00
ilgen . Emit ( OpCodes . Isinst , type ) ;
ilgen . Emit ( OpCodes . Ldnull ) ;
ilgen . Emit ( OpCodes . Cgt_Un ) ;
2004-10-19 17:43:55 +04:00
}
2005-06-01 13:49:30 +04:00
internal override void EmitCheckcast ( TypeWrapper context , ILGenerator ilgen )
2004-10-19 17:43:55 +04:00
{
2005-06-01 13:49:30 +04:00
if ( IsRemapped )
2004-10-19 17:43:55 +04:00
{
2005-06-01 13:49:30 +04:00
TypeWrapper shadow = ClassLoaderWrapper . GetWrapperFromTypeFast ( type ) ;
MethodInfo method = shadow . TypeAsBaseType . GetMethod ( "__<checkcast>" ) ;
if ( method ! = null )
{
ilgen . Emit ( OpCodes . Call , method ) ;
return ;
}
2004-10-19 17:43:55 +04:00
}
2005-06-01 13:49:30 +04:00
EmitHelper . Castclass ( ilgen , type ) ;
2004-10-19 17:43:55 +04:00
}
2005-12-07 12:06:32 +03:00
#endif
2005-01-03 11:26:21 +03:00
2005-08-05 12:40:54 +04:00
internal override void Finish ( )
2005-01-03 11:26:21 +03:00
{
2006-03-01 15:26:25 +03:00
if ( BaseTypeWrapper ! = null )
{
BaseTypeWrapper . Finish ( ) ;
}
foreach ( TypeWrapper tw in this . Interfaces )
{
tw . Finish ( ) ;
}
2005-06-01 13:49:30 +04:00
// TODO instead of linking here, we should just pre-link in LazyPublishMembers
foreach ( MethodWrapper mw in GetMethods ( ) )
{
mw . Link ( ) ;
}
foreach ( FieldWrapper fw in GetFields ( ) )
{
fw . Link ( ) ;
}
2005-01-03 11:26:21 +03:00
}
2005-10-01 15:16:11 +04:00
internal override string GetGenericSignature ( )
{
return null ;
}
internal override string GetGenericMethodSignature ( MethodWrapper mw )
{
return null ;
}
internal override string GetGenericFieldSignature ( FieldWrapper fw )
{
return null ;
}
internal override string [ ] GetEnclosingMethod ( )
{
return null ;
}
2005-11-01 17:01:42 +03:00
internal override object [ ] GetDeclaredAnnotations ( )
{
return type . GetCustomAttributes ( false ) ;
}
2005-01-03 11:26:21 +03:00
}
2003-08-21 14:06:34 +04:00
2005-06-01 13:49:30 +04:00
sealed class ArrayTypeWrapper : TypeWrapper
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
private static TypeWrapper [ ] interfaces ;
private static MethodInfo clone ;
private Type type ;
private Modifiers reflectiveModifiers ;
2006-03-23 14:57:41 +03:00
private ClassLoaderWrapper classLoader ;
2005-01-03 11:26:21 +03:00
2005-06-01 13:49:30 +04:00
internal ArrayTypeWrapper ( Type type , Modifiers modifiers , Modifiers reflectiveModifiers , string name , ClassLoaderWrapper classLoader )
2006-03-23 14:57:41 +03:00
: base ( modifiers , name , CoreClasses . java . lang . Object . Wrapper )
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
this . type = type ;
this . reflectiveModifiers = reflectiveModifiers ;
2006-03-23 14:57:41 +03:00
this . classLoader = classLoader ;
}
internal override ClassLoaderWrapper GetClassLoader ( )
{
return classLoader ;
2003-08-21 14:06:34 +04:00
}
2004-08-17 13:05:21 +04:00
2005-08-05 12:40:54 +04:00
internal static MethodInfo CloneMethod
2004-12-22 11:04:10 +03:00
{
2005-08-05 12:40:54 +04:00
get
2005-06-01 13:49:30 +04:00
{
2005-08-05 12:40:54 +04:00
if ( clone = = null )
{
clone = typeof ( Array ) . GetMethod ( "Clone" , BindingFlags . Public | BindingFlags . Instance , null , Type . EmptyTypes , null ) ;
}
return clone ;
2005-06-01 13:49:30 +04:00
}
2005-08-05 12:40:54 +04:00
}
protected override void LazyPublishMembers ( )
{
MethodWrapper mw = new SimpleCallMethodWrapper ( this , "clone" , "()Ljava.lang.Object;" , CloneMethod , CoreClasses . java . lang . Object . Wrapper , TypeWrapper . EmptyArray , Modifiers . Public , MemberFlags . HideFromReflection , SimpleOpCode . Callvirt , SimpleOpCode . Callvirt ) ;
2005-06-01 13:49:30 +04:00
mw . Link ( ) ;
SetMethods ( new MethodWrapper [ ] { mw } ) ;
SetFields ( FieldWrapper . EmptyArray ) ;
2004-12-22 11:04:10 +03:00
}
2005-06-01 13:49:30 +04:00
internal override Modifiers ReflectiveModifiers
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
get
{
return reflectiveModifiers ;
}
2003-08-21 14:06:34 +04:00
}
2005-06-01 13:49:30 +04:00
internal override Assembly Assembly
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
get
{
return type . Assembly ;
}
2003-02-22 15:28:12 +03:00
}
2005-06-01 13:49:30 +04:00
internal override string SigName
2003-02-22 15:28:12 +03:00
{
2005-06-01 13:49:30 +04:00
get
2003-02-22 15:28:12 +03:00
{
2005-06-01 13:49:30 +04:00
// for arrays the signature name is the same as the normal name
return Name ;
2003-02-22 15:28:12 +03:00
}
}
2005-06-01 13:49:30 +04:00
internal override TypeWrapper [ ] Interfaces
{
get
{
if ( interfaces = = null )
{
TypeWrapper [ ] tw = new TypeWrapper [ 2 ] ;
tw [ 0 ] = ClassLoaderWrapper . LoadClassCritical ( "java.lang.Cloneable" ) ;
tw [ 1 ] = ClassLoaderWrapper . LoadClassCritical ( "java.io.Serializable" ) ;
interfaces = tw ;
}
return interfaces ;
}
}
internal override TypeWrapper [ ] InnerClasses
2003-02-22 15:28:12 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
return TypeWrapper . EmptyArray ;
}
2003-02-22 15:28:12 +03:00
}
2005-06-01 13:49:30 +04:00
internal override TypeWrapper DeclaringTypeWrapper
2003-02-22 15:28:12 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
return null ;
}
2003-02-22 15:28:12 +03:00
}
2005-06-01 13:49:30 +04:00
internal override Type TypeAsTBD
2003-02-22 15:28:12 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
return type ;
}
2003-02-22 15:28:12 +03:00
}
2005-06-01 13:49:30 +04:00
private bool IsFinished
2003-02-22 15:28:12 +03:00
{
2005-06-01 13:49:30 +04:00
get
2003-02-22 15:28:12 +03:00
{
2005-06-01 13:49:30 +04:00
Type elem = type . GetElementType ( ) ;
while ( elem . IsArray )
{
elem = elem . GetElementType ( ) ;
}
return ! ( elem is TypeBuilder ) ;
2003-02-22 15:28:12 +03:00
}
}
2005-08-05 12:40:54 +04:00
internal override void Finish ( )
2003-02-22 15:28:12 +03:00
{
2005-06-01 13:49:30 +04:00
lock ( this )
2003-02-22 15:28:12 +03:00
{
2005-06-01 13:49:30 +04:00
// TODO optimize this
if ( ! IsFinished )
{
TypeWrapper elementTypeWrapper = ElementTypeWrapper ;
Type elementType = elementTypeWrapper . TypeAsArrayType ;
elementTypeWrapper . Finish ( ) ;
type = elementType . Assembly . GetType ( elementType . FullName + "[]" , true ) ;
ClassLoaderWrapper . SetWrapperForType ( type , this ) ;
}
2003-02-22 15:28:12 +03:00
}
}
2005-10-01 15:16:11 +04:00
internal override string GetGenericSignature ( )
{
return null ;
}
internal override string GetGenericMethodSignature ( MethodWrapper mw )
{
return null ;
}
internal override string GetGenericFieldSignature ( FieldWrapper fw )
{
return null ;
}
internal override string [ ] GetEnclosingMethod ( )
{
return null ;
}
2003-02-22 15:28:12 +03:00
}
}