dotgnu-pnet-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[dotgnu-pnet-commits] pnet ChangeLog engine/convert.c engine/cvmc.c e...


From: Klaus Treichel
Subject: [dotgnu-pnet-commits] pnet ChangeLog engine/convert.c engine/cvmc.c e...
Date: Tue, 16 Jan 2007 06:46:09 +0000

CVSROOT:        /cvsroot/dotgnu-pnet
Module name:    pnet
Changes by:     Klaus Treichel <ktreichel>      07/01/16 06:46:08

Modified files:
        .              : ChangeLog 
        engine         : convert.c cvmc.c cvmc_call.c cvmc_obj.c 
                         cvmc_setup.c engine.h jitc.c jitc_array.c 
                         jitc_call.c jitc_delegate.c jitc_except.c 
                         jitc_obj.c jitc_pinvoke.c jitc_setup.c 
                         lib_helpers.c lookup.c Makefile.am null_coder.c 
        image          : program.h 
        include        : il_coder.h 
Added files:
        engine         : cctormgr.c cctormgr.h 

Log message:
        Replace emitting calls to the cctors in the code by using a cctor 
manager.

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/pnet/ChangeLog?cvsroot=dotgnu-pnet&r1=1.3401&r2=1.3402
http://cvs.savannah.gnu.org/viewcvs/pnet/engine/convert.c?cvsroot=dotgnu-pnet&r1=1.27&r2=1.28
http://cvs.savannah.gnu.org/viewcvs/pnet/engine/cvmc.c?cvsroot=dotgnu-pnet&r1=1.49&r2=1.50
http://cvs.savannah.gnu.org/viewcvs/pnet/engine/cvmc_call.c?cvsroot=dotgnu-pnet&r1=1.33&r2=1.34
http://cvs.savannah.gnu.org/viewcvs/pnet/engine/cvmc_obj.c?cvsroot=dotgnu-pnet&r1=1.20&r2=1.21
http://cvs.savannah.gnu.org/viewcvs/pnet/engine/cvmc_setup.c?cvsroot=dotgnu-pnet&r1=1.43&r2=1.44
http://cvs.savannah.gnu.org/viewcvs/pnet/engine/engine.h?cvsroot=dotgnu-pnet&r1=1.116&r2=1.117
http://cvs.savannah.gnu.org/viewcvs/pnet/engine/jitc.c?cvsroot=dotgnu-pnet&r1=1.63&r2=1.64
http://cvs.savannah.gnu.org/viewcvs/pnet/engine/jitc_array.c?cvsroot=dotgnu-pnet&r1=1.6&r2=1.7
http://cvs.savannah.gnu.org/viewcvs/pnet/engine/jitc_call.c?cvsroot=dotgnu-pnet&r1=1.33&r2=1.34
http://cvs.savannah.gnu.org/viewcvs/pnet/engine/jitc_delegate.c?cvsroot=dotgnu-pnet&r1=1.8&r2=1.9
http://cvs.savannah.gnu.org/viewcvs/pnet/engine/jitc_except.c?cvsroot=dotgnu-pnet&r1=1.13&r2=1.14
http://cvs.savannah.gnu.org/viewcvs/pnet/engine/jitc_obj.c?cvsroot=dotgnu-pnet&r1=1.25&r2=1.26
http://cvs.savannah.gnu.org/viewcvs/pnet/engine/jitc_pinvoke.c?cvsroot=dotgnu-pnet&r1=1.6&r2=1.7
http://cvs.savannah.gnu.org/viewcvs/pnet/engine/jitc_setup.c?cvsroot=dotgnu-pnet&r1=1.20&r2=1.21
http://cvs.savannah.gnu.org/viewcvs/pnet/engine/lib_helpers.c?cvsroot=dotgnu-pnet&r1=1.13&r2=1.14
http://cvs.savannah.gnu.org/viewcvs/pnet/engine/lookup.c?cvsroot=dotgnu-pnet&r1=1.15&r2=1.16
http://cvs.savannah.gnu.org/viewcvs/pnet/engine/Makefile.am?cvsroot=dotgnu-pnet&r1=1.92&r2=1.93
http://cvs.savannah.gnu.org/viewcvs/pnet/engine/null_coder.c?cvsroot=dotgnu-pnet&r1=1.27&r2=1.28
http://cvs.savannah.gnu.org/viewcvs/pnet/engine/cctormgr.c?cvsroot=dotgnu-pnet&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/pnet/engine/cctormgr.h?cvsroot=dotgnu-pnet&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/pnet/image/program.h?cvsroot=dotgnu-pnet&r1=1.22&r2=1.23
http://cvs.savannah.gnu.org/viewcvs/pnet/include/il_coder.h?cvsroot=dotgnu-pnet&r1=1.52&r2=1.53

Patches:
Index: ChangeLog
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnet/ChangeLog,v
retrieving revision 1.3401
retrieving revision 1.3402
diff -u -b -r1.3401 -r1.3402
--- ChangeLog   7 Jan 2007 16:28:53 -0000       1.3401
+++ ChangeLog   16 Jan 2007 06:46:08 -0000      1.3402
@@ -1,3 +1,55 @@
+2006-01-16  Klaus Treichel  <address@hidden>
+
+       * include/il_coder.h: Add the functions runCCtors to execute the queued
+       cctors during generating the current method and runCCtor to run one 
class
+       initializerand the helper macros for the new slots.
+
+       * image/program.h: Add the new system internal attribute
+       IL_META_TYPEDEF_CCTOR_RUNNING to the type attributes to detect is a 
cctor
+       is allready executing and to avoid to execute it recursively.
+
+       * engine/cctormgr.c, engine/cctormgr.h: Added new manager functions for
+       running the class initializers. This one makes sure that initializers 
are
+       executed only once and methods relying on the execution of a class
+       initializer in a different thread wait for it's completition.
+
+       * engine/convert.c: Acquire the metadata lock during generation of a 
method
+       with the jit coder. Call the new coder method RunCCtors after a method 
was
+       successfully generated.
+
+       * engine/cvmc.c: Add the cctor manager to the cvm coder class and add 
the
+       new coder functions for running the cctors.
+
+       * engine/cvmc_call.c: Replace the inline call to the cctor with queueing
+       the execution of the cctor in the cctor manager.
+
+       * engine/cvmc_obj.c: Replace the inline call to the cctor with queueing
+       the execution of the cctor in the cctor manager.
+
+       * engine/cvmc_setup.c: Remove the cctor once instruction for static
+       constructors.
+
+       * engine/engine.h: Add the decalaration of the new function 
_ILLookupClass.
+
+       * engine/lib_helpers.c: Use une new coder function for running the 
cctors
+       in _IL_RuntimeHelpers_RunClassConstructor.
+
+       * engine/lookup.c: Add the function _ILLookupClass to find a class by 
name
+       without laying out the class and use this function in LookupClass.
+
+       * engine/null_coder.c: Add the stubs Coder_RunCCtors and Coder_RunCCtor 
for
+        the new coder functions.
+
+       * engine/jitc.c, engine/jitc_array.c, engine/jitc_call.c,
+       engine/jitc_delegate.c, engine/jitc_except.c, engine/jitc_obj.c,
+       engine/jitc_pinvoke.c,, engine/jitc_setup.c: Add support for the cctor
+       manager. Replace function calls acquiring metadata locks with the non
+       locking ones. (ILSizeOfType -> _ILSizeOfTypeLocked, ...) to avoid
+       deadlocks.
+
+       * engine/Makefile.am: Add the new files cctormgr.c and cctormgr.h to the
+       engine sources.
+
 2006-01-07  Klaus Treichel  <address@hidden>
 
        * engine/heap.c: Add _ILEngineAllocTyped to allocate memory for objects

Index: engine/convert.c
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnet/engine/convert.c,v
retrieving revision 1.27
retrieving revision 1.28
diff -u -b -r1.27 -r1.28
--- engine/convert.c    20 Oct 2006 19:30:54 -0000      1.27
+++ engine/convert.c    16 Jan 2007 06:46:08 -0000      1.28
@@ -36,7 +36,24 @@
 #define        IL_CONVERT_TYPE_INIT            5
 #define        IL_CONVERT_DLL_NOT_FOUND        6
 
+/*
+ * Acquire and release the metadata lock, while suppressing finalizers
+ * during the execution of "ConvertMethod".
+ */
+#define        METADATA_WRLOCK(thread) \
+                       do { \
+                               
IL_METADATA_WRLOCK(_ILExecThreadProcess(thread)); \
+                               ILGCDisableFinalizers(0); \
+                       } while (0)
+#define        METADATA_UNLOCK(thread) \
+                       do { \
+                               ILGCEnableFinalizers(); \
+                               
IL_METADATA_UNLOCK(_ILExecThreadProcess(thread)); \
+                               ILGCInvokeFinalizers(0); \
+                       } while (0)
+
 #ifdef IL_USE_JIT
+
 /*
  * Inner version of "_ILConvertMethod", which detects the type of
  * exception to throw, but does not throw it.
@@ -70,17 +87,18 @@
           method is written in IL or not */
        if(code.code)
        {
-               /* Disable the finalizers so that the coder will not be called 
resursively. */
-               ILGCDisableFinalizers(0);
+               /* We need the metadata write lock */
+               METADATA_WRLOCK(thread);
                /* Use the bytecode verifier and coder to convert the method */
                if(!_ILVerify(coder, &start, method, &code,
                                          
ILImageIsSecure(ILProgramItem_Image(method)), thread))
                {
-                       ILGCEnableFinalizers();
+                       METADATA_UNLOCK(thread);
                        *errorCode = IL_CONVERT_VERIFY_FAILED;
                        return 0;
                }
-               ILGCEnableFinalizers();
+               /* Run the needed cctors and unlock the metadata too */
+               ILCoderRunCCtors(coder);
        }
        else
        {
@@ -148,22 +166,6 @@
 #endif /* IL_CONFIG_PINVOKE */
 
 /*
- * Acquire and release the metadata lock, while suppressing finalizers
- * during the execution of "ConvertMethod".
- */
-#define        METADATA_WRLOCK(thread) \
-                       do { \
-                               
IL_METADATA_WRLOCK(_ILExecThreadProcess(thread)); \
-                               ILGCDisableFinalizers(0); \
-                       } while (0)
-#define        METADATA_UNLOCK(thread) \
-                       do { \
-                               ILGCEnableFinalizers(); \
-                               
IL_METADATA_UNLOCK(_ILExecThreadProcess(thread)); \
-                               ILGCInvokeFinalizers(0); \
-                       } while (0)
-
-/*
  * Inner version of "_ILConvertMethod", which detects the type of
  * exception to throw, but does not throw it.
  */
@@ -506,7 +508,8 @@
        ILThreadAtomicStart();
        method->userData = (void *)start;
        ILThreadAtomicEnd();
-       METADATA_UNLOCK(thread);
+       /* Run the needed cctors and unlock the metadata too */
+       ILCoderRunCCtors(coder);
        *errorCode = IL_CONVERT_OK;
        return start;
 }

Index: engine/cvmc.c
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnet/engine/cvmc.c,v
retrieving revision 1.49
retrieving revision 1.50
diff -u -b -r1.49 -r1.50
--- engine/cvmc.c       30 Aug 2006 17:33:25 -0000      1.49
+++ engine/cvmc.c       16 Jan 2007 06:46:08 -0000      1.50
@@ -32,6 +32,7 @@
 #include "lib_defs.h"
 #include "method_cache.h"
 #include "cvm_config.h"
+#include "cctormgr.h"
 #if defined(HAVE_LIBFFI)
 #include "ffi.h"
 #endif
@@ -91,6 +92,8 @@
        long                    nativeArgPosn;
        long                    nativeArgHeight;
        ILExecProcess  *process;                /* Backpointer to the owning 
process */
+       /* The manager for running the required cctors. */
+       ILCCtorMgr              cctorMgr;
 };
 
 /*
@@ -160,6 +163,12 @@
                ILFree(coder);
                return 0;
        }
+       if(!ILCCtorMgr_Init(&(coder->cctorMgr), 10))
+       {
+               ILCacheDestroy(coder->cache);
+               ILFree(coder);
+               return 0;
+       }
        coder->start = 0;
        coder->stackCheck = 0;
        coder->needTry = 0;
@@ -230,6 +239,7 @@
 {
        ILCVMCoder *coder = (ILCVMCoder *)_coder;
        ILCacheDestroy(coder->cache);
+       ILCCtorMgr_Destroy(&(coder->cctorMgr));
        if(coder->argOffsets)
        {
                ILFree(coder->argOffsets);
@@ -278,6 +288,24 @@
 }
 
 /*
+ * Run the class initializers queued during generation of the last method.
+ */
+static ILInt32 CVMCoder_RunCCtors(ILCoder *_coder)
+{
+       ILCVMCoder *coder = (ILCVMCoder *)_coder;
+       return ILCCtorMgr_RunCCtors(&(coder->cctorMgr));
+}
+
+/*
+ * Run the class initializer for the given class.
+ */
+static ILInt32 CVMCoder_RunCCtor(ILCoder *_coder, ILClass *classInfo)
+{
+       ILCVMCoder *coder = (ILCVMCoder *)_coder;
+       return ILCCtorMgr_RunCCtor(&(coder->cctorMgr), classInfo);
+}
+
+/*
  * Get a block of method cache memory for use in code unrolling.
  */
 int _ILCVMStartUnrollBlock(ILCoder *_coder, int align, ILCachePosn *posn)
@@ -485,6 +513,8 @@
        CVMCoder_CheckNull,
        CVMCoder_Convert,
        CVMCoder_ConvertCustom,
+       CVMCoder_RunCCtors,
+       CVMCoder_RunCCtor,
        "sentinel"
 };
 

Index: engine/cvmc_call.c
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnet/engine/cvmc_call.c,v
retrieving revision 1.33
retrieving revision 1.34
diff -u -b -r1.33 -r1.34
--- engine/cvmc_call.c  22 Oct 2006 18:01:08 -0000      1.33
+++ engine/cvmc_call.c  16 Jan 2007 06:46:08 -0000      1.34
@@ -57,52 +57,6 @@
 }
 
 /*
- * Call the static constructor for a class if necessary.
- */
-static void CallStaticConstructor(ILCoder *coder, ILClass *classInfo,
-                                                                 int isCtor)
-{
-       if((classInfo->attributes & IL_META_TYPEDEF_CCTOR_ONCE) != 0)
-       {
-               /* We already know that the static constructor has been called,
-                  so there is no point outputting a call to it again */
-               return;
-       }
-       if(isCtor ||
-          (classInfo->attributes & IL_META_TYPEDEF_BEFORE_FIELD_INIT) == 0)
-       {
-               /* We must call the static constructor before instance
-                  constructors, or before static methods when the
-                  "beforefieldinit" attribute is not present */
-               ILMethod *cctor = 0;
-               while((cctor = (ILMethod *)ILClassNextMemberByKind
-                                       (classInfo, (ILMember *)cctor,
-                                        IL_META_MEMBERKIND_METHOD)) != 0)
-               {
-                       if(ILMethod_IsStaticConstructor(cctor))
-                       {
-                               break;
-                       }
-               }
-               if(cctor != 0)
-               {
-                       /* Don't call it if we are within the constructor 
already */
-                       if(cctor != ((ILCVMCoder *)coder)->currentMethod)
-                       {
-                               /* Output a call to the static constructor */
-                               CVM_OUT_PTR(COP_CALL, cctor);
-                       }
-               }
-               else
-               {
-                       /* This class does not have a static constructor,
-                          so mark it so that we never do this test again */
-                       classInfo->attributes |= IL_META_TYPEDEF_CCTOR_ONCE;
-               }
-       }
-}
-
-/*
  * Adjust the position of the stack for a call.
  */
 static void AdjustForCall(ILCoder *coder, ILCoderMethodInfo *info,
@@ -143,7 +97,8 @@
                                                                
ILEngineStackItem *returnItem,
                                                                ILMethod 
*methodInfo)
 {
-       CallStaticConstructor(coder, ILMethod_Owner(methodInfo), 0);
+       /* Queue the cctor to run. */
+       ILCCtorMgr_OnCallMethod(&(((ILCVMCoder *)coder)->cctorMgr), methodInfo);
        if(info->tailCall)
        {
                CVMP_OUT_PTR(COP_PREFIX_TAIL_CALL, methodInfo);
@@ -173,7 +128,8 @@
 static void CVMCoder_CallCtor(ILCoder *coder, ILCoderMethodInfo *info,
                                                          ILMethod *methodInfo)
 {
-       CallStaticConstructor(coder, ILMethod_Owner(methodInfo), 1);
+       /* Queue the cctor to run. */
+       ILCCtorMgr_OnCallMethod(&(((ILCVMCoder *)coder)->cctorMgr), methodInfo);
        CVM_OUT_PTR(COP_CALL_CTOR, methodInfo);
        AdjustForCall(coder, info, 0);
        CVM_ADJUST(1);

Index: engine/cvmc_obj.c
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnet/engine/cvmc_obj.c,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -b -r1.20 -r1.21
--- engine/cvmc_obj.c   23 Aug 2005 10:45:52 -0000      1.20
+++ engine/cvmc_obj.c   16 Jan 2007 06:46:08 -0000      1.21
@@ -321,10 +321,6 @@
                                 fieldType, field->offset, 1);
 }
 
-/* Forward declaration: defined in "cvmc_call.c" */
-static void CallStaticConstructor(ILCoder *coder, ILClass *classInfo,
-                                                                 int isCtor);
-
 #ifdef IL_CONFIG_PINVOKE
 
 /*
@@ -391,9 +387,10 @@
 #endif
        if((field->member.attributes & IL_META_FIELDDEF_HAS_FIELD_RVA) == 0)
        {
-               /* Call the static constructor if necessary */
                classInfo = ILField_Owner(field);
-               CallStaticConstructor(coder, classInfo, 1);
+
+               /* Queue the cctor to run. */
+               ILCCtorMgr_OnStaticFieldAccess(&(((ILCVMCoder 
*)coder)->cctorMgr), field);
 
                /* Regular or thread-static field? */
                if(!ILFieldIsThreadStatic(field))
@@ -477,9 +474,10 @@
        }
 #endif
 
-       /* Call the static constructor if necessary */
        classInfo = ILField_Owner(field);
-       CallStaticConstructor(coder, classInfo, 1);
+
+       /* Queue the cctor to run. */
+       ILCCtorMgr_OnStaticFieldAccess(&(((ILCVMCoder *)coder)->cctorMgr), 
field);
 
        /* Regular or RVA field? */
        if((field->member.attributes & IL_META_FIELDDEF_HAS_FIELD_RVA) == 0)
@@ -822,9 +820,10 @@
        ILPInvoke *pinvoke;
 #endif
 
-       /* Call the static constructor if necessary */
        classInfo = ILField_Owner(field);
-       CallStaticConstructor(coder, classInfo, 1);
+
+       /* Queue the cctor to run. */
+       ILCCtorMgr_OnStaticFieldAccess(&(((ILCVMCoder *)coder)->cctorMgr), 
field);
 
        /* Regular or RVA field? */
 #ifdef IL_CONFIG_PINVOKE

Index: engine/cvmc_setup.c
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnet/engine/cvmc_setup.c,v
retrieving revision 1.43
retrieving revision 1.44
diff -u -b -r1.43 -r1.44
--- engine/cvmc_setup.c 30 Aug 2006 17:33:25 -0000      1.43
+++ engine/cvmc_setup.c 16 Jan 2007 06:46:08 -0000      1.44
@@ -279,14 +279,6 @@
        /* Set the number of arguments, which initialize's the method's frame */
        CVM_OUT_WIDE(COP_SET_NUM_ARGS, ctx->numArgWords);
 
-       /* Is this a static constructor? */
-       if(ILMethod_IsStaticConstructor(method))
-       {
-               /* Output a "cctor_once" instruction to ensure that this
-                  method's body can only be executed once */
-               CVM_OUT_NONE(COP_CCTOR_ONCE);
-       }
-
        /* If this is a constructor, then back-patch the push down size,
           which is one less than the number of argument words */
        if(isConstructor)

Index: engine/engine.h
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnet/engine/engine.h,v
retrieving revision 1.116
retrieving revision 1.117
diff -u -b -r1.116 -r1.117
--- engine/engine.h     1 Jan 2007 17:09:40 -0000       1.116
+++ engine/engine.h     16 Jan 2007 06:46:08 -0000      1.117
@@ -830,6 +830,13 @@
 int _ILGetInternalDelegate(ILMethod *method, int *isCtor,  ILInternalInfo 
*info);
 
 /*
+ * Look up a class name that is length-specified.
+ */
+ILClass *_ILLookupClass(ILExecProcess *process,
+                                               const char *className,
+                                               int classNameLen);
+
+/*
  * Look up an interface method.  Returns NULL if not found.
  */
 ILMethod *_ILLookupInterfaceMethod(ILClassPrivate *objectClassPrivate,

Index: engine/jitc.c
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnet/engine/jitc.c,v
retrieving revision 1.63
retrieving revision 1.64
diff -u -b -r1.63 -r1.64
--- engine/jitc.c       1 Jan 2007 17:09:40 -0000       1.63
+++ engine/jitc.c       16 Jan 2007 06:46:08 -0000      1.64
@@ -24,6 +24,7 @@
 
 #ifdef IL_USE_JIT
 
+#include "cctormgr.h"
 #include "il_opcodes.h"
 #include "il_utils.h"
 #ifdef IL_DEBUGGER
@@ -72,6 +73,22 @@
  */
 /* #define _IL_JIT_ENABLE_INLINE 1 */
 
+/*
+ * To enable the cctor manager uncomment define the following define.
+ */
+#define IL_JIT_ENABLE_CCTORMGR
+
+/*
+ * Reenable finalizers, unlock the metadata lock and run finalizers.
+ * Must be kept in sync with convert.c
+ */
+#define        METADATA_UNLOCK(thread) \
+                       do { \
+                               ILGCEnableFinalizers(); \
+                               
IL_METADATA_UNLOCK(_ILExecThreadProcess(thread)); \
+                               ILGCInvokeFinalizers(0); \
+                       } while (0)
+
 #ifdef _IL_JIT_DUMP_FUNCTION
 #ifndef _IL_JIT_ENABLE_DEBUG
 #define _IL_JIT_ENABLE_DEBUG 1
@@ -415,6 +432,9 @@
        jit_label_t     nextBlock;
        jit_label_t     rethrowBlock;
 
+       /* The manager for running the required cctors. */
+       ILCCtorMgr              cctorMgr;
+
 #ifndef IL_JIT_THREAD_IN_SIGNATURE
        /* cache for the current thread. */
        ILJitValue              thread;
@@ -493,18 +513,6 @@
        }
 
 /*
- * Acquire and release the metadata lock during layouting a class.
- */
-#define        METADATA_WRLOCK(thread) \
-                       do { \
-                               
IL_METADATA_WRLOCK(_ILExecThreadProcess(thread)); \
-                       } while (0)
-#define        METADATA_UNLOCK(thread) \
-                       do { \
-                               
IL_METADATA_UNLOCK(_ILExecThreadProcess(thread)); \
-                       } while (0)
-
-/*
  * Check if the typeKind is a floating point number.
  */
 #define _JIT_TYPEKIND_IS_FLOAT(typeKind) \
@@ -1269,17 +1277,12 @@
  */
 static int _LayoutClass(ILExecThread *thread, ILClass *info)
 {
-       int result = 0;
-
        /* Check if the class is allready layouted. */
        if((info->userData) && !(((ILClassPrivate 
*)(info->userData))->inLayout))
        {
                return 1;
        }
-       METADATA_WRLOCK(thread);
-       result = _ILLayoutClass(_ILExecThreadProcess(thread), info);
-       METADATA_UNLOCK(thread);
-       return result; 
+       return _ILLayoutClass(_ILExecThreadProcess(thread), info);
 }
 
 /*
@@ -1956,6 +1959,7 @@
        return((ILUInt32)jit_type_get_size(classPrivate->jitTypes.jitTypeBase));
 }
 
+#ifndef IL_JIT_ENABLE_CCTORMGR
 /*
  * Call the static constructor for a class if necessary.
  */
@@ -2011,6 +2015,7 @@
                }
        }
 }
+#endif /* !IL_JIT_ENABLE_CCTORMGR */
 
 /*
  * The exception handler which converts libjit inbuilt exceptions
@@ -2462,6 +2467,13 @@
        /* Init the current jitted function. */
        coder->jitFunction = 0;
 
+       if(!ILCCtorMgr_Init(&(coder->cctorMgr), 10))
+       {
+               ILMemPoolDestroy(&(coder->methodPool));
+               ILFree(coder);
+               return 0;
+       }
+
 #ifndef IL_JIT_THREAD_IN_SIGNATURE
        coder->thread = 0;
 #endif
@@ -2679,6 +2691,8 @@
 
        ILMemPoolDestroy(&(coder->methodPool));
 
+       ILCCtorMgr_Destroy(&(coder->cctorMgr));
+
        ILFree(coder);
 }
 
@@ -2729,6 +2743,33 @@
 #endif
 }
 
+/*
+ * Run the class initializers queued during generation of the last method.
+ */
+static ILInt32 JITCoder_RunCCtors(ILCoder *coder)
+{
+#ifdef IL_JIT_ENABLE_CCTORMGR
+       ILJITCoder *jitCoder = _ILCoderToILJITCoder(coder);
+
+       return ILCCtorMgr_RunCCtors(&(jitCoder->cctorMgr));
+#else  /* !IL_JIT_ENABLE_CCTORMGR */
+       ILExecThread *thread = ILExecThreadCurrent();
+
+       METADATA_UNLOCK(thread);
+       return 1;
+#endif /* !IL_JIT_ENABLE_CCTORMGR */
+}
+
+/*
+ * Run the class initializer for the given class.
+ */
+static ILInt32 JITCoder_RunCCtor(ILCoder *coder, ILClass *classInfo)
+{
+       ILJITCoder *jitCoder = _ILCoderToILJITCoder(coder);
+
+       return ILCCtorMgr_RunCCtor(&(jitCoder->cctorMgr), classInfo);
+}
+
 #ifdef IL_CONFIG_PINVOKE
 
 /*
@@ -4507,6 +4548,7 @@
        JITCoder_CheckNull,
        JITCoder_Convert,
        JITCoder_ConvertCustom,
+       JITCoder_RunCCtors,
        "sentinel"
 };
 #ifdef __cplusplus

Index: engine/jitc_array.c
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnet/engine/jitc_array.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -b -r1.6 -r1.7
--- engine/jitc_array.c 17 Dec 2006 10:31:32 -0000      1.6
+++ engine/jitc_array.c 16 Jan 2007 06:46:08 -0000      1.7
@@ -202,7 +202,7 @@
        }
 
        /* Get the size of one array element. */
-       elementSize = ILSizeOfType(thread, elementType);
+       elementSize = _ILSizeOfTypeLocked(_ILExecThreadProcess(thread), 
elementType);
 
        totalSize = (((ILUInt64)elementSize) * ((ILUInt64)length)) + 
_IL_JIT_SARRAY_HEADERSIZE;
        if(totalSize > (ILUInt64)IL_MAX_INT32)
@@ -302,7 +302,7 @@
                elementType = ILType_ElemType(ILClassGetSynType(arrayClass));
 
                /* Get the size of one array element. */
-               elementSize = ILSizeOfType(thread, elementType);
+               elementSize = _ILSizeOfTypeLocked(jitCoder->process, 
elementType);
 
                elementClass = ILClassFromType(ILProgramItem_Image(arrayClass),
                                                                           0, 
elementType, 0);

Index: engine/jitc_call.c
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnet/engine/jitc_call.c,v
retrieving revision 1.33
retrieving revision 1.34
diff -u -b -r1.33 -r1.34
--- engine/jitc_call.c  1 Jan 2007 17:09:40 -0000       1.33
+++ engine/jitc_call.c  16 Jan 2007 06:46:08 -0000      1.34
@@ -323,7 +323,7 @@
                                                        
(ILContextNextImage(jitCoder->process->context, 0),
                                                        0, paramType, 0);
                        info = ILClassResolve(info);
-                       typeSize = ILSizeOfType(_thread, paramType);
+                       typeSize = _ILSizeOfTypeLocked(jitCoder->process, 
paramType);
 
                        boxObject = _ILJitAllocObjectGen(jitCoder->jitFunction, 
info);
                        if(boxValue)
@@ -480,8 +480,13 @@
                ILMutexUnlock(globalTraceMutex);
        }
 #endif
+#ifdef IL_JIT_ENABLE_CCTORMGR
+       /* Queue the cctor to run. */
+       ILCCtorMgr_OnCallMethod(&(jitCoder->cctorMgr), methodInfo);
+#else  /* !IL_JIT_ENABLE_CCTORMGR */
        /* Output a call to the static constructor */
        _ILJitCallStaticConstructor(jitCoder, ILMethod_Owner(methodInfo), 0);
+#endif /* !IL_JIT_ENABLE_CCTORMGR */
 
 #if !defined(IL_CONFIG_REDUCE_CODE) && !defined(IL_WITHOUT_TOOLS) && 
defined(_IL_JIT_ENABLE_DEBUG)
        methodName = _ILJitFunctionGetMethodName(jitFunction);
@@ -822,8 +827,13 @@
        type = ILType_FromClass(classInfo);
        synType = ILClassGetSynType(classInfo);
 
+#ifdef IL_JIT_ENABLE_CCTORMGR
+       /* Queue the cctor to run. */
+       ILCCtorMgr_OnCallMethod(&(jitCoder->cctorMgr), methodInfo);
+#else  /* !IL_JIT_ENABLE_CCTORMGR */
        /* Output a call to the static constructor */
        _ILJitCallStaticConstructor(jitCoder, ILMethod_Owner(methodInfo), 1);
+#endif /* !IL_JIT_ENABLE_CCTORMGR */
 
        /* Check if the function is implemented in the engine. */
        if((internalType = _ILJitFunctionIsInternal(jitCoder, methodInfo, 
&fnInfo, 1)))

Index: engine/jitc_delegate.c
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnet/engine/jitc_delegate.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -b -r1.8 -r1.9
--- engine/jitc_delegate.c      1 Jan 2007 17:09:40 -0000       1.8
+++ engine/jitc_delegate.c      16 Jan 2007 06:46:08 -0000      1.9
@@ -178,7 +178,7 @@
                                                        
(ILContextNextImage(_thread->process->context, 0),
                                                        0, paramType, 0);
                        info = ILClassResolve(info);
-                       typeSize = ILSizeOfType(_thread, paramType);
+                       typeSize = 
_ILSizeOfTypeLocked(_ILExecThreadProcess(_thread), paramType);
 
                        boxObject = _ILJitAllocObjectGen(jitFunction, info);
                        if(boxValue)
@@ -252,7 +252,7 @@
                {
                        ILJitType jitType = _ILJitGetReturnType(paramType, 
_ILExecThreadProcess(_thread));
 
-                       ILUInt32 typeSize = ILSizeOfType(_thread, paramType);
+                       ILUInt32 typeSize = 
_ILSizeOfTypeLocked(_ILExecThreadProcess(_thread), paramType);
                        ILJitValue boxObjectSize = 
jit_value_create_nint_constant(jitFunction,
                                                                                
                                                          _IL_JIT_TYPE_UINT32,
                                                                                
                                                          typeSize);

Index: engine/jitc_except.c
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnet/engine/jitc_except.c,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -b -r1.13 -r1.14
--- engine/jitc_except.c        17 Oct 2006 12:24:18 -0000      1.13
+++ engine/jitc_except.c        16 Jan 2007 06:46:08 -0000      1.14
@@ -99,8 +99,9 @@
        }
        if(exception > 0)
        {
-               ILClass *classInfo = ILExecThreadLookupClass(_thread,
-                                                                               
                         exceptionClasses[exception]);
+               ILClass *classInfo = 
_ILLookupClass(_ILExecThreadProcess(_thread),
+                                                                               
        exceptionClasses[exception],
+                                                                               
        strlen(exceptionClasses[exception]));
                ILJitValue info;
                if(!classInfo)
                {

Index: engine/jitc_obj.c
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnet/engine/jitc_obj.c,v
retrieving revision 1.25
retrieving revision 1.26
diff -u -b -r1.25 -r1.26
--- engine/jitc_obj.c   1 Jan 2007 17:09:40 -0000       1.25
+++ engine/jitc_obj.c   16 Jan 2007 06:46:08 -0000      1.26
@@ -432,8 +432,13 @@
 #endif
        if((field->member.attributes & IL_META_FIELDDEF_HAS_FIELD_RVA) == 0)
        {
+       #ifdef IL_JIT_ENABLE_CCTORMGR
+               /* Queue the cctor to run. */
+               ILCCtorMgr_OnStaticFieldAccess(&(jitCoder->cctorMgr), field);   
+       #else   /* !IL_JIT_ENABLE_CCTORMGR */
                /* Output a call to the static constructor */
                _ILJitCallStaticConstructor(jitCoder, ILField_Owner(field), 1);
+       #endif  /* !IL_JIT_ENABLE_CCTORMGR */
 
                /* Regular or thread-static field? */
                if(!ILFieldIsThreadStatic(field))
@@ -568,8 +573,13 @@
        }
 #endif
 
+#ifdef IL_JIT_ENABLE_CCTORMGR
+       /* Queue the cctor to run. */
+       ILCCtorMgr_OnStaticFieldAccess(&(jitCoder->cctorMgr), field);   
+#else  /* !IL_JIT_ENABLE_CCTORMGR */
        /* Output a call to the static constructor */
        _ILJitCallStaticConstructor(jitCoder, ILField_Owner(field), 1);
+#endif /* !IL_JIT_ENABLE_CCTORMGR */
 
        /* Regular or RVA field? */
        if((field->member.attributes & IL_META_FIELDDEF_HAS_FIELD_RVA) == 0)
@@ -693,8 +703,13 @@
        /* Pop the value off the stack. */
        _ILJitStackPop(jitCoder, stackItem);
 
+#ifdef IL_JIT_ENABLE_CCTORMGR
+       /* Queue the cctor to run. */
+       ILCCtorMgr_OnStaticFieldAccess(&(jitCoder->cctorMgr), field);   
+#else  /* !IL_JIT_ENABLE_CCTORMGR */
        /* Output a call to the static constructor */
        _ILJitCallStaticConstructor(jitCoder, ILField_Owner(field), 1);
+#endif /* !IL_JIT_ENABLE_CCTORMGR */
 
 #ifdef IL_CONFIG_PINVOKE
        if((field->member.attributes & IL_META_FIELDDEF_PINVOKE_IMPL) != 0 &&

Index: engine/jitc_pinvoke.c
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnet/engine/jitc_pinvoke.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -b -r1.6 -r1.7
--- engine/jitc_pinvoke.c       17 Oct 2006 12:24:18 -0000      1.6
+++ engine/jitc_pinvoke.c       16 Jan 2007 06:46:08 -0000      1.7
@@ -1228,10 +1228,10 @@
                    thread = ILExecThreadCurrent();
                    srcElemSize = jit_value_create_nint_constant(function,
                                                                        
_IL_JIT_TYPE_INT32,
-                                                                       
(jit_nint)(ILSizeOfType(thread, elemType)));
+                                                                       
(jit_nint)(_ILSizeOfTypeLocked(_ILExecThreadProcess(thread), elemType)));
                    newElemSize = jit_value_create_nint_constant(function,
                                                                        
_IL_JIT_TYPE_INT32,
-                                                                       
(jit_nint)(ILSizeOfType(thread, elemType)));
+                                                                       
(jit_nint)(_ILSizeOfTypeLocked(_ILExecThreadProcess(thread), elemType)));
                    newArraySize = jit_insn_mul(function, arraySize, 
newElemSize);
                    args[0] = newArraySize;
                    jit_insn_store(function, newArray, 
jit_insn_call_native(function, "ILGCAllocAtomic",
@@ -1290,7 +1290,7 @@
 {
         ILClass *classInfo = 
ILClassResolve(ILType_ToValueType(structureILType));
        ILExecThread *thread = ILExecThreadCurrent();
-        unsigned int structSize = ILSizeOfType(thread, structureILType);
+        unsigned int structSize = 
_ILSizeOfTypeLocked(_ILExecThreadProcess(thread), structureILType);
        ILField *field = 0;
        ILType *type;
 
@@ -1650,7 +1650,7 @@
 {
     ILClass *classInfo = ILClassResolve(ILType_ToValueType(structureILType));
     ILExecThread *thread = ILExecThreadCurrent();
-    unsigned int structSize = ILSizeOfType(thread, structureILType);
+    unsigned int structSize = 
_ILSizeOfTypeLocked(_ILExecThreadProcess(thread), structureILType);
     ILField *field = 0;
     ILJitValue newStruct = 0;
     ILType *type;
@@ -1947,10 +1947,10 @@
                            thread = ILExecThreadCurrent();
                            srcElemSize = 
jit_value_create_nint_constant(function,
                                                                                
_IL_JIT_TYPE_INT32,
-                                                                               
(jit_nint)(ILSizeOfType(thread, elemType)));                        
+                                                                               
(jit_nint)(_ILSizeOfTypeLocked(_ILExecThreadProcess(thread), elemType)));
                            newElemSize = 
jit_value_create_nint_constant(function,
                                                                                
_IL_JIT_TYPE_INT32,
-                                                                               
(jit_nint)(ILSizeOfType(thread, elemType)));
+                                                                               
(jit_nint)(_ILSizeOfTypeLocked(_ILExecThreadProcess(thread), elemType)));
                            newArray = jit_insn_add_relative(function, 
outAddressValue, (jit_nint)(sizeof(ILUInt32)));
                            jit_insn_branch_if(function,
                                                jit_insn_eq(function, arraySize,
@@ -2806,6 +2806,8 @@
 
            if(ILType_IsSimpleArray(type))
            {
+                               ILExecThread *thread = ILExecThreadCurrent();
+
                            srcArray = in;
                            if(addressKind==MARSHAL_ITEM_OF_STRUCTURE || 
addressKind==MARSHAL_ITEM_OF_ARRAY)
                                    srcArray = jit_insn_load_relative(function, 
srcArray, offset, _IL_JIT_TYPE_VPTR);
@@ -2818,11 +2820,11 @@
                            arraySize = jit_insn_load_relative(function, 
srcArray, 0, _IL_JIT_TYPE_UINT32);
                            srcElemSize = 
jit_value_create_nint_constant(function,
                                                                            
_IL_JIT_TYPE_INT32,
-                                                                           
(jit_nint)(ILSizeOfType(ILExecThreadCurrent(),
+                                                                           
(jit_nint)(_ILSizeOfTypeLocked(_ILExecThreadProcess(thread),
                                                                                
                    elemType)));
                            newElemSize = 
jit_value_create_nint_constant(function,
                                                                            
_IL_JIT_TYPE_INT32,
-                                                                           
(jit_nint)(ILSizeOfType(ILExecThreadCurrent(),
+                                                                           
(jit_nint)(_ILSizeOfTypeLocked(_ILExecThreadProcess(thread),
                                                                                
                    elemType)));
                            newArraySize = jit_insn_mul(function, arraySize, 
newElemSize);
                            newArraySize = jit_insn_add_relative(function, 
newArraySize, (jit_nint)(sizeof(ILUInt32)));
@@ -2889,8 +2891,9 @@
 ILJitValue MarshalDelegateStruct(jit_function_t function, ILJitValue 
inAddress, ILType *structureILType,
                                    ILUInt32 marshalType, ILJitValue 
outAddress, jit_nint offset, unsigned int addressKind)
 {
+       ILExecThread *thread = ILExecThreadCurrent();
     ILClass *classInfo = ILClassResolve(ILType_ToValueType(structureILType));
-    unsigned int structSize = ILSizeOfType(ILExecThreadCurrent(), 
structureILType);
+    unsigned int structSize = 
_ILSizeOfTypeLocked(_ILExecThreadProcess(thread), structureILType);
     ILField *field = 0;
     ILType *type;
     ILJitType structType;
@@ -3266,8 +3269,9 @@
                                                    ILUInt32 marshalType, 
ILJitValue outAddress, jit_nint offset,
                                                    unsigned int addressKind)
 {
+       ILExecThread *thread = ILExecThreadCurrent();
         ILClass *classInfo = 
ILClassResolve(ILType_ToValueType(structureILType));
-        unsigned int structSize = ILSizeOfType(ILExecThreadCurrent(), 
structureILType);
+       unsigned int structSize = 
_ILSizeOfTypeLocked(_ILExecThreadProcess(thread), structureILType);
        ILField *field = 0;
        ILType *type;
 
@@ -3604,10 +3608,10 @@
                            arraySize = jit_insn_load_relative(function, 
srcArray, 0, _IL_JIT_TYPE_UINT32);
                            srcElemSize = 
jit_value_create_nint_constant(function,
                                                                                
_IL_JIT_TYPE_INT32,
-                                                                               
(jit_nint)(ILSizeOfType(thread, elemType)));
+                                                                               
(jit_nint)(_ILSizeOfTypeLocked(_ILExecThreadProcess(thread), elemType)));
                            newElemSize = 
jit_value_create_nint_constant(function,
                                                                                
_IL_JIT_TYPE_INT32,
-                                                                               
(jit_nint)(ILSizeOfType(thread, elemType)));
+                                                                               
(jit_nint)(_ILSizeOfTypeLocked(_ILExecThreadProcess(thread), elemType)));
 
                            jit_insn_branch_if(function,
                                                jit_insn_eq(function, arraySize,

Index: engine/jitc_setup.c
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnet/engine/jitc_setup.c,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -b -r1.20 -r1.21
--- engine/jitc_setup.c 11 Dec 2006 20:40:11 -0000      1.20
+++ engine/jitc_setup.c 16 Jan 2007 06:46:08 -0000      1.21
@@ -67,6 +67,7 @@
        }
 #endif
 
+#ifndef IL_JIT_ENABLE_CCTORMGR
        if(ILMethod_IsStaticConstructor(method))
        {
                /* We have to take care that the method is executed only once. 
*/
@@ -105,6 +106,7 @@
                   other blocks are later moved to the function start. */
                jit_insn_move_blocks_to_start(coder->jitFunction, startLabel, 
endLabel);
        }
+#endif /* !IL_JIT_ENABLE_CCTORMGR */
 
 #ifdef IL_DEBUGGER
        /* Check if this method can be debugged */
@@ -233,19 +235,25 @@
                ILMutexUnlock(globalTraceMutex);
        }
 #endif
-#ifdef _IL_JIT_DISASSEMBLE_FUNCTION
-       if(jitCoder->flags & IL_CODER_FLAG_STATS)
-       {
                if(!jit_function_compile(jitCoder->jitFunction))
                {
                        return IL_CODER_END_TOO_BIG;
                }
+#ifdef _IL_JIT_DISASSEMBLE_FUNCTION
+       if(jitCoder->flags & IL_CODER_FLAG_STATS)
+       {
                ILMutexLock(globalTraceMutex);
                jit_dump_function(stdout, jitCoder->jitFunction, methodName);
                ILMutexUnlock(globalTraceMutex);
        }
 #endif
 #endif
+#ifdef IL_JIT_ENABLE_CCTORMGR
+       /* Unlock the context because we possibly have to build cctors before */
+       /* this method will be executed. (It's a hack for now.) */
+       jit_context_build_end(jitCoder->context);
+#endif /* IL_JIT_ENABLE_CCTORMGR */
+
        return IL_CODER_END_OK;
 }
 

Index: engine/lib_helpers.c
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnet/engine/lib_helpers.c,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -b -r1.13 -r1.14
--- engine/lib_helpers.c        17 Dec 2006 10:31:32 -0000      1.13
+++ engine/lib_helpers.c        16 Jan 2007 06:46:08 -0000      1.14
@@ -270,29 +270,9 @@
 #else
        ILClass *classInfo = *((ILClass **)type);
 #endif
-       ILMethod *method;
-       if(classInfo)
-       {
-               /* Locate the static constructor within the class */
-               IL_METADATA_RDLOCK(_ILExecThreadProcess(thread));
-               method = 0;
-               while((method = (ILMethod *)ILClassNextMemberByKind
-                       (classInfo, (ILMember *)method, 
IL_META_MEMBERKIND_METHOD)) != 0)
-               {
-                       if(ILMethod_IsStaticConstructor(method))
-                       {
-                               break;
-                       }
-               }
-               IL_METADATA_UNLOCK(_ILExecThreadProcess(thread));
+       ILCoder *coder = _ILExecThreadProcess(thread)->coder;
 
-               /* Call the static constructor if we found it.  The method
-                  itself contains instructions that prevent multiple calls */
-               if(method)
-               {
-                       ILExecThreadCall(thread, method, (void *)0);
-               }
-       }
+       ILCoderRunCCtor(coder, classInfo);
 }
 
 ILInt32 _IL_RuntimeHelpers_InternalOffsetToStringData(ILExecThread *thread)

Index: engine/lookup.c
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnet/engine/lookup.c,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -b -r1.15 -r1.16
--- engine/lookup.c     23 Aug 2005 10:45:52 -0000      1.15
+++ engine/lookup.c     16 Jan 2007 06:46:08 -0000      1.16
@@ -77,6 +77,33 @@
 static ILClass *LookupClass(ILExecThread *thread, const char *className,
                                                        int classNameLen)
 {
+       ILClass *classInfo = _ILLookupClass(_ILExecThreadProcess(thread),
+                                                                               
className,
+                                                                               
classNameLen);
+
+       /* Make sure that the class has been laid out */
+       if(classInfo != 0)
+       {
+               IL_METADATA_WRLOCK(_ILExecThreadProcess(thread));
+               if(!_ILLayoutClass(_ILExecThreadProcess(thread), classInfo))
+               {
+                       IL_METADATA_UNLOCK(_ILExecThreadProcess(thread));
+                       return 0;
+               }
+               IL_METADATA_UNLOCK(_ILExecThreadProcess(thread));
+       }
+
+       /* Return the final class structure to the caller */
+       return classInfo;
+}
+
+/*
+ * Look up a class name that is length-specified.
+ */
+ILClass *_ILLookupClass(ILExecProcess *process,
+                                               const char *className,
+                                               int classNameLen)
+{
        int len, dot;
        const char *name;
        int nameLen;
@@ -119,7 +146,7 @@
        {
                /* Try looking in the system image first, to prevent the
                   application from redirecting system types elsewhere */
-               image = ILContextGetSystem(thread->process->context);
+               image = ILContextGetSystem(process->context);
                if(image)
                {
                        classInfo = ILClassLookupLen(ILClassGlobalScope(image),
@@ -129,7 +156,7 @@
        }
        if(!classInfo)
        {
-               classInfo = ILClassLookupGlobalLen(thread->process->context,
+               classInfo = ILClassLookupGlobalLen(process->context,
                                                                                
   name, nameLen,
                                                                                
   namespace, namespaceLen);
        }
@@ -149,18 +176,6 @@
                                                                         name, 
nameLen, 0, 0);
        }
 
-       /* Make sure that the class has been laid out */
-       if(classInfo != 0)
-       {
-               IL_METADATA_WRLOCK(_ILExecThreadProcess(thread));
-               if(!_ILLayoutClass(_ILExecThreadProcess(thread), classInfo))
-               {
-                       IL_METADATA_UNLOCK(_ILExecThreadProcess(thread));
-                       return 0;
-               }
-               IL_METADATA_UNLOCK(_ILExecThreadProcess(thread));
-       }
-
        /* Return the final class structure to the caller */
        return classInfo;
 }

Index: engine/Makefile.am
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnet/engine/Makefile.am,v
retrieving revision 1.92
retrieving revision 1.93
diff -u -b -r1.92 -r1.93
--- engine/Makefile.am  11 Dec 2006 20:40:11 -0000      1.92
+++ engine/Makefile.am  16 Jan 2007 06:46:08 -0000      1.93
@@ -89,7 +89,9 @@
 BUILT_SOURCES = gen_marshal.c \
                                gen_marshal.h
 
-libILEngine_a_SOURCES = cvm.c \
+libILEngine_a_SOURCES = cctormgr.c \
+                                               cctormgr.h \
+                                               cvm.c \
                                                box.c \
                                                call.c \
                                                convert.c \

Index: engine/null_coder.c
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnet/engine/null_coder.c,v
retrieving revision 1.27
retrieving revision 1.28
diff -u -b -r1.27 -r1.28
--- engine/null_coder.c 23 Aug 2005 10:45:52 -0000      1.27
+++ engine/null_coder.c 16 Jan 2007 06:46:08 -0000      1.28
@@ -418,6 +418,14 @@
                                                        void *customName, void 
*customCookie)
 {
 }
+static ILInt32 Coder_RunCCtors(ILCoder *coder)
+{
+       return 1;
+}
+static ILInt32 Coder_RunCCtor(ILCoder *coder, ILClass *classInfo)
+{
+       return 1;
+}
 
 /*
  * Null coder class and instance.
@@ -528,6 +536,8 @@
        Coder_CheckNull,
        Coder_Convert,
        Coder_ConvertCustom,
+       Coder_RunCCtors,
+       Coder_RunCCtor,
        "sentinel"
 };
 ILCoder _ILNullCoder = {&_ILNullCoderClass};

Index: image/program.h
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnet/image/program.h,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -b -r1.22 -r1.23
--- image/program.h     22 Apr 2005 16:08:05 -0000      1.22
+++ image/program.h     16 Jan 2007 06:46:08 -0000      1.23
@@ -286,10 +286,12 @@
  */
 #define        IL_META_TYPEDEF_REFERENCE               0x80000000      /* Not 
yet really defined */
 #define        IL_META_TYPEDEF_COMPLETE                0x40000000      /* 
Definition is complete */
-#define        IL_META_TYPEDEF_CCTOR_ONCE              0x20000000      /* 
.cctor already done */
-#define        IL_META_TYPEDEF_GENERIC_PARS    0x10000000      /* Has generic 
parameters */
-#define        IL_META_TYPEDEF_CLASS_EXPANDED  0x08000000      /* Generics 
expanded */
-#define        IL_META_TYPEDEF_SYSTEM_MASK             0xF8000000      /* 
System flags */
+#define        IL_META_TYPEDEF_GENERIC_PARS    0x20000000      /* Has generic 
parameters */
+#define        IL_META_TYPEDEF_CLASS_EXPANDED  0x10000000      /* Generics 
expanded */
+#define        IL_META_TYPEDEF_CCTOR_RUNNING   0x08000000      /* .cctor is 
currenty executed. */
+#define        IL_META_TYPEDEF_CCTOR_ONCE              0x04000000      /* 
.cctor already done */
+#define        IL_META_TYPEDEF_CCTOR_MASK              0x0C000000      /* 
.cctor flags */
+#define        IL_META_TYPEDEF_SYSTEM_MASK             0xFC000000      /* 
System flags */
 
 /*
  * Information about an "implements" clause for a class.

Index: include/il_coder.h
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnet/include/il_coder.h,v
retrieving revision 1.52
retrieving revision 1.53
diff -u -b -r1.52 -r1.53
--- include/il_coder.h  22 Oct 2006 18:01:09 -0000      1.52
+++ include/il_coder.h  16 Jan 2007 06:46:08 -0000      1.53
@@ -811,6 +811,20 @@
                                                  void *customName, void 
*customCookie);
 
        /*
+        * Run the cctors collected during code generation.
+        * This function must be called after the method is compiled 
successfully
+        * and before the method itself is executed.
+        * The metadata lock must be still accuired and will be released just
+        * before the cctors are executed.
+     */
+       ILInt32 (*runCCtors)(ILCoder *coder);
+
+       /*
+        * Run the class initializer for the given class.
+        */
+       ILInt32 (*runCCtor)(ILCoder *coder, ILClass *classInfo);
+
+       /*
         * Sentinel string to catch missing methods in class tables.
         */
        const char *sentinel;
@@ -1089,6 +1103,10 @@
                                                                                
                        (customCookie)))
 #define        ILCoderMarkEnd(coder) \
                        ((*((coder)->classInfo->markEnd))((coder)))
+#define        ILCoderRunCCtors(coder) \
+                       ((*((coder)->classInfo->runCCtors))((coder)))
+#define        ILCoderRunCCtor(coder, classInfo) \
+                       ((*((coder)->classInfo->runCCtor))((coder),(classInfo)))
 
 #ifdef __cplusplus
 };

Index: engine/cctormgr.c
===================================================================
RCS file: engine/cctormgr.c
diff -N engine/cctormgr.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ engine/cctormgr.c   16 Jan 2007 06:46:08 -0000      1.1
@@ -0,0 +1,466 @@
+/*
+ * cctormgr.c - Queue and execute class initializers (static constructors).
+ *
+ * Copyright (C) 2001  Southern Storm Software, Pty Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "cctormgr.h"
+#include "lib_defs.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Reenable finalizers, unlock the metadata lock and run finalizers.
+ * Must be kept in sync with convert.c
+ */
+#define        METADATA_UNLOCK(thread) \
+                       do { \
+                               ILGCEnableFinalizers(); \
+                               
IL_METADATA_UNLOCK(_ILExecThreadProcess(thread)); \
+                               ILGCInvokeFinalizers(0); \
+                       } while (0)
+/*
+ * Get the number of queued cctors.
+ */
+static ILInt32 _ILCCtorMgr_GetNumQueuedCCtors(ILCCtorMgr *cctorMgr)
+{
+       ILInt32 numQueuedCCtors = 0;
+       ILClassEntry *classEntry = cctorMgr->lastClass;
+
+       while(classEntry)
+       {
+               numQueuedCCtors++;
+               classEntry = classEntry->prevClass;
+       }
+       return numQueuedCCtors;
+}
+
+/*
+ * Execute the cctor of the given class.
+ * This function must be executed with the current thread holding the
+ * cctor manager's lock.
+ */
+static int _ILCCtorMgr_RunCCtor(ILCCtorMgr *cctorMgr,
+                                                               ILExecThread 
*thread,
+                                                               ILClass 
*classInfo)
+{
+       if((classInfo->attributes &
+               (IL_META_TYPEDEF_CCTOR_RUNNING | IL_META_TYPEDEF_CCTOR_ONCE)) 
== 0)
+       {
+               /* The cctor was not allready executed and is not currently 
running. */
+               /* So find the cctor now. */
+               ILMethod *cctor = 0;
+
+               IL_METADATA_RDLOCK(_ILExecThreadProcess(thread));
+               while((cctor = (ILMethod *)ILClassNextMemberByKind(classInfo,
+                                                                               
                                  (ILMember *)cctor,
+                                                                               
                                  IL_META_MEMBERKIND_METHOD)) != 0)
+               {
+                       if(ILMethod_IsStaticConstructor(cctor))
+                       {
+                               break;
+                       }
+               }
+               IL_METADATA_UNLOCK(_ILExecThreadProcess(thread));
+               if(cctor)
+               {
+                       /* We found the cctor so we can execute it now. */
+                       classInfo->attributes |= IL_META_TYPEDEF_CCTOR_RUNNING;
+                       if(ILExecThreadCall(thread, cctor, 0))
+                       {
+                               return 0;
+                       }
+               }
+               classInfo->attributes |= IL_META_TYPEDEF_CCTOR_ONCE;
+       }
+       return 1;
+}
+
+/*
+ * Execute the queued cctors.
+ * This function must be executed with the current thread holding the
+ * cctor manager's lock.
+ */
+static int _ILCCtorMgr_RunCCtors(ILCCtorMgr *cctorMgr,
+                                                                ILExecThread 
*thread,
+                                                                ILClass 
*classes[],
+                                                                ILInt32 
numClasses)
+{
+       ILInt32 currentCCtor;
+
+       /* And run the cctors now. */
+       for(currentCCtor = 0; currentCCtor < numClasses; currentCCtor++)
+       {
+               if(!(_ILCCtorMgr_RunCCtor(cctorMgr,
+                                                                 thread,
+                                                                 
classes[currentCCtor])))
+               {
+                       return 0;
+               }
+       }
+       return 1;
+}
+
+/*
+ * Lookup the class entry for the given class in the cctor manager and return
+ * the pointer to the class entry or add a new class entry and return the
+ * pointer to the newly created entry.
+ * Returns 0 on out of memory.
+ */
+static ILClassEntry *ILCCtorMgr_FindOrAddClass(ILCCtorMgr *cctorMgr,
+                                                                               
           ILClass *classInfo)
+{
+       ILClassEntry *currentClass = cctorMgr->lastClass;
+
+       while(currentClass)
+       {
+               if(currentClass->classInfo == classInfo)
+               {
+                       return currentClass;
+               }
+               currentClass = currentClass->prevClass;
+       }
+
+       /* Add the new class to the queue. */
+       if(!(currentClass = ILMemPoolAlloc(&(cctorMgr->classPool),
+                                                                          
ILClassEntry)))
+       {
+               return 0;
+       }
+       /* Now fill the class entry with the current class. */
+       currentClass->classInfo = classInfo;
+       currentClass->prevClass = cctorMgr->lastClass;
+       cctorMgr->lastClass = currentClass;
+
+       return currentClass;
+}
+
+/*
+ * Add a class to the queue of the classes which have to be initialized.
+ */
+static int _ILCCtorMgr_QueueClass(ILCCtorMgr *cctorMgr,
+                                                 ILClass *classInfo)
+{
+       ILMethod *cctor = 0;
+       ILClassEntry *currentClass = 0;
+
+       if(!cctorMgr)
+       {
+               return 0;
+       }
+
+       if(!classInfo)
+       {
+               return 0;
+       }
+
+       if((classInfo->attributes & IL_META_TYPEDEF_CCTOR_ONCE) != 0)
+       {
+               /* We already know that the static constructor has been 
executed, */
+               return 1;
+       }
+
+       while((cctor = (ILMethod *)ILClassNextMemberByKind(classInfo,
+                                                                               
                          (ILMember *)cctor,
+                                                                               
                          IL_META_MEMBERKIND_METHOD)) != 0)
+       {
+               if(ILMethod_IsStaticConstructor(cctor))
+               {
+                       break;
+               }
+       }
+       if(cctor == 0)
+       {
+               /* We couldn't find a cctor. */
+               /* So we flag the class as if the cctor was executed. */
+               classInfo->attributes |= IL_META_TYPEDEF_CCTOR_ONCE;
+               return 1;
+       }
+
+       /* Check if the class is allready in the queue or add it. */
+       if(!(currentClass = ILCCtorMgr_FindOrAddClass(cctorMgr, classInfo)))
+       {
+               return 0;
+       }
+
+       /* And exit with success. */
+       return 1;
+}
+
+/*
+ * Throw a System.TypeInitializationException.
+ */
+static void _ILCCtorMgr_ThrowTypeInitializationException(ILExecThread *thread)
+{
+       ILObject *exception = ILExecThreadGetException(thread);
+
+       if(exception)
+       {
+               ILObject *typeInitializationException = 0;
+
+               ILExecThreadClearException(thread);
+
+               ILExecThreadThrowSystem(thread,
+                                                               
"System.TypeInitializationException",
+                                                                0);
+
+               typeInitializationException = ILExecThreadGetException(thread);
+               if(typeInitializationException)
+               {
+                       /* Set the inner exception thrown by the class 
initializer. */
+                       ((System_Exception 
*)typeInitializationException)->innerException = (System_Exception *)exception;
+               }
+       }
+}
+
+/*
+ * Initialize a cctor manager instance.
+ */
+int ILCCtorMgr_Init(ILCCtorMgr *cctorMgr,
+                                                  ILInt32 numCCtorEntries)
+{
+       if(cctorMgr)
+       {
+               /* Initialize the lock mutex. */
+               if(!(cctorMgr->lock = ILMutexCreate()))
+               {
+                       return 0;
+               }
+               cctorMgr->thread = (ILThread *)0;;
+               cctorMgr->currentMethod = (ILMethod *)0;
+               cctorMgr->isStaticConstructor = 0;
+
+               cctorMgr->lastClass = (ILClassEntry *)0;
+
+               /* Intialize the pool for the class infos. */
+               ILMemPoolInit(&(cctorMgr->classPool),
+                                         sizeof(ILClassEntry),
+                                         numCCtorEntries);
+
+               return 1;
+       }
+       return 0;
+}
+
+/*
+ * Destroy a cctor manager instance.
+ */
+void ILCCtorMgr_Destroy(ILCCtorMgr *cctorMgr)
+{
+       if(cctorMgr)
+       {
+               ILMemPoolDestroy(&(cctorMgr->classPool));
+
+               if(cctorMgr->lock)
+               {
+                       /* Destroy the lock mutex. */
+                       ILMutexDestroy(cctorMgr->lock);
+               }
+       }
+}
+
+/*
+ * Call this method before any non virtual method call is done.
+ * It checks if the static constructor for the method owner has to be invoked
+ * before the call is done.
+ */
+int ILCCtorMgr_OnCallMethod(ILCCtorMgr *cctorMgr,
+                                                       ILMethod *method)
+{
+       ILClass *methodOwner = ILMethod_Owner(method);
+
+       if((methodOwner->attributes & IL_META_TYPEDEF_CCTOR_ONCE) != 0)
+       {
+               /* We already know that the static constructor has been called, 
*/
+               return 1;
+       }
+
+       if((methodOwner->attributes & IL_META_TYPEDEF_BEFORE_FIELD_INIT) == 0)
+       {
+               if(ILMethod_IsStatic(method))
+               {
+                       /* We have to call the cctor before calling any static 
method */
+                       /* of this type */
+                       return _ILCCtorMgr_QueueClass(cctorMgr, methodOwner);
+
+               }
+               if(ILMethod_IsConstructor(method))
+               {
+                       /* We have to call the cctor before calling a 
constructor of */
+                       /* this type. */
+                       return _ILCCtorMgr_QueueClass(cctorMgr, methodOwner);
+               }
+       }
+       return 1;
+}
+
+/*
+ * Call this method before accessing any static field.
+ * It checks if the static constructor for the field's owner has to be invoked
+ * before the field is accessed.
+ */
+int ILCCtorMgr_OnStaticFieldAccess(ILCCtorMgr *cctorMgr,
+                                                                  ILField 
*field)
+{
+       ILClass *fieldOwner = ILField_Owner(field);
+
+       if((fieldOwner->attributes & IL_META_TYPEDEF_CCTOR_ONCE) != 0)
+       {
+               /* We already know that the static constructor has been called, 
*/
+               return 1;
+       }
+
+       if(ILField_IsStatic(field))
+       {
+               /* We have to call the cctor before accessing any static field 
*/
+               /* of this type */
+               return _ILCCtorMgr_QueueClass(cctorMgr, fieldOwner);
+       }
+       return 1;
+}
+
+/*
+ * Run the cctor for the given class.
+ */
+int ILCCtorMgr_RunCCtor(ILCCtorMgr *cctorMgr, ILClass *classInfo)
+{
+       if((cctorMgr != 0) && (classInfo != 0))
+       {
+               if((classInfo->attributes & IL_META_TYPEDEF_CCTOR_ONCE) != 0)
+               {
+                       /* We already know that the static constructor has been 
called, */
+                       return 1;
+               }
+               else
+               {
+                       ILExecThread *thread = ILExecThreadCurrent();
+                       int result;
+
+                       if(cctorMgr->thread == thread->supportThread)
+                       {
+                               /* We allready hold the cctor lock. */
+                               result = _ILCCtorMgr_RunCCtor(cctorMgr,
+                                                                               
          thread,
+                                                                               
          classInfo);
+                       }
+                       else
+                       {
+                               /* Lock the cctor manager. */
+                               ILMutexLock(cctorMgr->lock);
+
+                               /* And set the thread holding the lock. */
+                               cctorMgr->thread = thread->supportThread;
+
+                               result = _ILCCtorMgr_RunCCtor(cctorMgr,
+                                                                               
          thread,
+                                                                               
          classInfo);
+
+                               /* reset the thread holding the lock. */
+                               cctorMgr->thread = (ILThread *)0;
+                               /* and unlock the cctor manager. */
+                               ILMutexUnlock(cctorMgr->lock);
+                       }
+                       if(!result)
+                       {
+                               
_ILCCtorMgr_ThrowTypeInitializationException(thread);
+                       }
+                       return result;
+               }
+       }
+       return 0;
+}
+
+/*
+ * Run the queued cctors.
+ */
+int ILCCtorMgr_RunCCtors(ILCCtorMgr *cctorMgr)
+{
+       if(cctorMgr)
+       {
+               ILExecThread *thread = ILExecThreadCurrent();
+
+               if(!(cctorMgr->lastClass))
+               {
+                       /* There are no cctors queued. */
+                       /* So unlock the metadata. */
+                       METADATA_UNLOCK(thread);
+                       /* and return with success. */
+                       return 1;
+               }
+               else
+               {
+                       int result;
+                       ILInt32 numQueuedCCtors = 
_ILCCtorMgr_GetNumQueuedCCtors(cctorMgr);
+                       ILClass *classes[numQueuedCCtors];
+                       ILClassEntry *classEntry = cctorMgr->lastClass;
+                       ILInt32 currentCCtor;
+
+                       /* Copy the cctors to execute to the class array. */
+                       for(currentCCtor = 0; currentCCtor < numQueuedCCtors; 
currentCCtor++)
+                       {
+                               classes[currentCCtor] = classEntry->classInfo;
+                               classEntry = classEntry->prevClass;
+                       }
+
+                       /* and reset the queue in the cctor manager. */
+                       cctorMgr->lastClass = (ILClassEntry *)0;
+                       ILMemPoolClear(&(cctorMgr->classPool));
+
+                       /* Now unlock the metadata. */
+                       METADATA_UNLOCK(thread);
+
+                       if(cctorMgr->thread == thread->supportThread)
+                       {
+                               /* We allready hold the cctor lock. */
+                               result = _ILCCtorMgr_RunCCtors(cctorMgr,
+                                                                               
           thread,
+                                                                               
           classes,
+                                                                               
           numQueuedCCtors);
+                       }
+                       else
+                       {
+                               /* Lock the cctor manager. */
+                               ILMutexLock(cctorMgr->lock);
+
+                               /* And set the thread holding the lock. */
+                               cctorMgr->thread = thread->supportThread;
+
+                               result = _ILCCtorMgr_RunCCtors(cctorMgr,
+                                                                               
           thread,
+                                                                               
           classes,
+                                                                               
           numQueuedCCtors);
+
+                               /* reset the thread holding the lock. */
+                               cctorMgr->thread = (ILThread *)0;
+                               /* and unlock the cctor manager. */
+                               ILMutexUnlock(cctorMgr->lock);
+                       }
+                       if(!result)
+                       {
+                               
_ILCCtorMgr_ThrowTypeInitializationException(thread);
+                       }
+                       return result;
+               }
+       }
+       return 0;
+}
+
+#ifdef __cplusplus
+};
+#endif

Index: engine/cctormgr.h
===================================================================
RCS file: engine/cctormgr.h
diff -N engine/cctormgr.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ engine/cctormgr.h   16 Jan 2007 06:46:08 -0000      1.1
@@ -0,0 +1,98 @@
+/*
+ * cctormgr.h - Header file for the cctor manager.
+ *
+ * Copyright (C) 2001  Southern Storm Software, Pty Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef        _ENGINE_CCTORMGR_H
+#define        _ENGINE_CCTORMGR_H
+
+#include "engine_private.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Forward declarations. */
+typedef struct _tagILClassEntry        ILClassEntry;
+typedef struct _tagILCCtorMgr  ILCCtorMgr;
+
+struct _tagILClassEntry
+{
+       ILClass            *classInfo;  /* The class for which the cctor has to 
be executed. */
+       ILClassEntry   *prevClass;      /* The previous class entry. */
+};
+
+struct _tagILCCtorMgr
+{
+       /* Mutex to synchronize the cctor execution. */
+       ILMutex            *lock;
+       
+       /* The thread holding the lock. */
+       ILThread           *thread;
+
+       /* The currently compiled method. */
+       ILMethod           *currentMethod;
+       /* Flag if the current method is a cctor. */
+       ILInt32                 isStaticConstructor;
+
+       /* Pool for the class entries. */
+       ILMemPool               classPool;
+       /* The last classentry  in the memory pool. */
+       ILClassEntry   *lastClass;
+
+};
+
+int ILCCtorMgr_Init(ILCCtorMgr *cctorMgr,
+                                                  ILInt32 numCCtorEntries);
+
+void ILCCtorMgr_Destroy(ILCCtorMgr *cctorMgr);
+
+/*
+ * Call this method before any non virtual method call is done.
+ * It checks if the static constructor for the method owner has to be invoked
+ * before the call is done.
+ */
+int ILCCtorMgr_OnCallMethod(ILCCtorMgr *cctorMgr,
+                                                       ILMethod *method);
+/*
+ * Call this method before accessing any static field.
+ * It checks if the static constructor for the field's owner has to be invoked
+ * before the field is accessed.
+ */
+int ILCCtorMgr_OnStaticFieldAccess(ILCCtorMgr *cctorMgr,
+                                                                  ILField 
*field);
+
+/*
+ * Run the cctor for the given class.
+ * Returns != 0 on success or 0 if an exception was thrown.
+ */
+int ILCCtorMgr_RunCCtor(ILCCtorMgr *cctorMgr, ILClass *classInfo);
+
+/*
+ * Run the queued cctors.
+ * Returns != 0 on success or 0 if an exception was thrown.
+ */
+int ILCCtorMgr_RunCCtors(ILCCtorMgr *cctorMgr);
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif /* !_ENGINE_CCTORMGR_H */
+




reply via email to

[Prev in Thread] Current Thread [Next in Thread]