[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[dotgnu-pnet-commits] pnet ChangeLog engine/cctormgr.c engine/cctormg...
From: |
Klaus Treichel |
Subject: |
[dotgnu-pnet-commits] pnet ChangeLog engine/cctormgr.c engine/cctormg... |
Date: |
Sun, 11 Feb 2007 14:34:33 +0000 |
CVSROOT: /cvsroot/dotgnu-pnet
Module name: pnet
Changes by: Klaus Treichel <ktreichel> 07/02/11 14:34:33
Modified files:
. : ChangeLog
engine : cctormgr.c cctormgr.h convert.c cvmc.c
cvmc_call.c jitc.c jitc_call.c jitc_except.c
jitc_inline.c jitc_obj.c jitc_setup.c
null_coder.c
include : il_coder.h il_thread.h
support : Makefile.am no_defs.h pt_defs.c pt_defs.h
w32_defs.h
Added files:
support : semaphore.c
Log message:
Add support for method locks while class initializers are executed.
CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/pnet/ChangeLog?cvsroot=dotgnu-pnet&r1=1.3413&r2=1.3414
http://cvs.savannah.gnu.org/viewcvs/pnet/engine/cctormgr.c?cvsroot=dotgnu-pnet&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/pnet/engine/cctormgr.h?cvsroot=dotgnu-pnet&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/pnet/engine/convert.c?cvsroot=dotgnu-pnet&r1=1.28&r2=1.29
http://cvs.savannah.gnu.org/viewcvs/pnet/engine/cvmc.c?cvsroot=dotgnu-pnet&r1=1.52&r2=1.53
http://cvs.savannah.gnu.org/viewcvs/pnet/engine/cvmc_call.c?cvsroot=dotgnu-pnet&r1=1.36&r2=1.37
http://cvs.savannah.gnu.org/viewcvs/pnet/engine/jitc.c?cvsroot=dotgnu-pnet&r1=1.67&r2=1.68
http://cvs.savannah.gnu.org/viewcvs/pnet/engine/jitc_call.c?cvsroot=dotgnu-pnet&r1=1.37&r2=1.38
http://cvs.savannah.gnu.org/viewcvs/pnet/engine/jitc_except.c?cvsroot=dotgnu-pnet&r1=1.15&r2=1.16
http://cvs.savannah.gnu.org/viewcvs/pnet/engine/jitc_inline.c?cvsroot=dotgnu-pnet&r1=1.3&r2=1.4
http://cvs.savannah.gnu.org/viewcvs/pnet/engine/jitc_obj.c?cvsroot=dotgnu-pnet&r1=1.27&r2=1.28
http://cvs.savannah.gnu.org/viewcvs/pnet/engine/jitc_setup.c?cvsroot=dotgnu-pnet&r1=1.25&r2=1.26
http://cvs.savannah.gnu.org/viewcvs/pnet/engine/null_coder.c?cvsroot=dotgnu-pnet&r1=1.28&r2=1.29
http://cvs.savannah.gnu.org/viewcvs/pnet/include/il_coder.h?cvsroot=dotgnu-pnet&r1=1.53&r2=1.54
http://cvs.savannah.gnu.org/viewcvs/pnet/include/il_thread.h?cvsroot=dotgnu-pnet&r1=1.27&r2=1.28
http://cvs.savannah.gnu.org/viewcvs/pnet/support/Makefile.am?cvsroot=dotgnu-pnet&r1=1.55&r2=1.56
http://cvs.savannah.gnu.org/viewcvs/pnet/support/no_defs.h?cvsroot=dotgnu-pnet&r1=1.4&r2=1.5
http://cvs.savannah.gnu.org/viewcvs/pnet/support/pt_defs.c?cvsroot=dotgnu-pnet&r1=1.9&r2=1.10
http://cvs.savannah.gnu.org/viewcvs/pnet/support/pt_defs.h?cvsroot=dotgnu-pnet&r1=1.10&r2=1.11
http://cvs.savannah.gnu.org/viewcvs/pnet/support/w32_defs.h?cvsroot=dotgnu-pnet&r1=1.8&r2=1.9
http://cvs.savannah.gnu.org/viewcvs/pnet/support/semaphore.c?cvsroot=dotgnu-pnet&rev=1.1
Patches:
Index: ChangeLog
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnet/ChangeLog,v
retrieving revision 1.3413
retrieving revision 1.3414
diff -u -b -r1.3413 -r1.3414
--- ChangeLog 9 Feb 2007 21:54:16 -0000 1.3413
+++ ChangeLog 11 Feb 2007 14:34:32 -0000 1.3414
@@ -1,3 +1,43 @@
+2007-02-11 Klaus Treichel <address@hidden>
+
+ * engine/cctormgr.c, engine/cctormgr.h: Add support for locking methods
+ that require class initializers to be executed till the class
initializers
+ finished executing.
+
+ * engine/convert.c: Use the new coder functions to handle the method
locks
+ for the cvm coder. Remove the execution of class initializers for the
jit
+ coder because that's handled in the coder itself.
+
+ * engine/cvmc.c: Add the new arg to the cctors execution and the method
to
+ handle the method locks.
+
+ * engine/cvmc_call.c: Remove the queueing of the class initializer on
+ loading a function pointer on the stack.
+
+ * engine/jitc.c: Use the new on-demand compilation feature in libjit to
+ handle the method locks. Add the new arg to the cctors execution and the
+ method to handle the method locks.
+
+ * engine/jitc_call.c, engine/jitc_except.c, engine/jitc_inline.c,
+ engine/jitc_obj.c, setup.c: Remove all conditionals if the cctor manager
+ is enabled because the other option is removed.
+
+ * engine/null_coder.c: Add the new arg to the cctors execution and the
+ method to handle the method locks.
+
+ * include/il_coder.h: Add the new arg to the cctors execution and the
+ method to handle the method locks to the coder definition.
+
+ * include/il_thread.h: Add function prototypes for semaphores.
+
+ * support/Makefile.am: Add the new file semaphores.c to the sources.
+
+ * support/pt_defs.c, support/pt_defs.h, support/no_defs.s,
+ support/win32_defs.h: Add a semaphore primitive for increasing the
+ semaphore count by more than 1.
+
+ * support/semaphore.c: Added.
+
2007-02-09 Radek Polak <address@hidden>
* dumpasm/Makefile.am, ildasm/Makefile.am, ildasm/ildasm_main.c,
Index: engine/cctormgr.c
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnet/engine/cctormgr.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- engine/cctormgr.c 21 Jan 2007 17:53:29 -0000 1.2
+++ engine/cctormgr.c 11 Feb 2007 14:34:32 -0000 1.3
@@ -26,15 +26,317 @@
#endif
/*
- * Reenable finalizers, unlock the metadata lock and run finalizers.
+ * Acquire and release the metadata lock, while suppressing finalizers
* Must be kept in sync with convert.c
*/
-#define METADATA_UNLOCK(thread) \
+#define METADATA_WRLOCK(process) \
+ do { \
+ IL_METADATA_WRLOCK(process); \
+ ILGCDisableFinalizers(0); \
+ } while (0)
+#define METADATA_UNLOCK(process) \
do { \
ILGCEnableFinalizers(); \
-
IL_METADATA_UNLOCK(_ILExecThreadProcess(thread)); \
+ IL_METADATA_UNLOCK(process); \
ILGCInvokeFinalizers(0); \
} while (0)
+
+/*
+ * Free an ILMethodLockEntry.
+ */
+static void _ILMethodLockEntry_Destroy(ILMethodLockPool *lockPool,
+
ILMethodLockEntry *lockEntry)
+{
+ if(lockPool && lockEntry)
+ {
+ /* Destroy the semaphore object. */
+ ILSemaphoreDestroy(lockEntry->sem);
+
+ /* And free the memory. */
+ ILFree(lockEntry->sem);
+
+ /* Free this lock entry. */
+ ILMemPoolFree(&(lockPool->methodPool), lockEntry);
+ }
+}
+
+/*
+ * Initialize a mathod lock pool.
+ */
+static int _ILMethodLockPool_Init(ILMethodLockPool *lockPool)
+{
+ if(lockPool)
+ {
+ /* Initialize the lock mutex. */
+ if(!(lockPool->lock = ILMutexCreate()))
+ {
+ return 0;
+ }
+
+ /* Intialize the pool for the class infos. */
+ ILMemPoolInit(&(lockPool->methodPool),
+ sizeof(ILMethodLockEntry),
+ 5);
+
+ lockPool->lastLockedMethod = 0;
+
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * Destroy a mathod lock pool.
+ */
+static int _ILMethodLockPool_Destroy(ILMethodLockPool *lockPool)
+{
+ if(lockPool)
+ {
+ ILMemPoolDestroy(&(lockPool->methodPool));
+
+ if(lockPool->lock)
+ {
+ /* Destroy the lock mutex. */
+ ILMutexDestroy(lockPool->lock);
+
+ ILFree(lockPool->lock);
+ }
+ }
+ return 0;
+}
+
+/*
+ * Add a method to the lock pool.
+ * Returns 0 on failure.
+ */
+static int _ILMethodLockPool_LockMethod(ILMethodLockPool *lockPool,
+
ILMethod *method,
+
void *userData)
+{
+ if(lockPool)
+ {
+ ILExecThread *thread = ILExecThreadCurrent();
+ ILMethodLockEntry *currentLockEntry;
+
+ ILMutexLock(lockPool->lock);
+
+ if(!(currentLockEntry = ILMemPoolAlloc(&(lockPool->methodPool),
+
ILMethodLockEntry)))
+ {
+ ILMutexUnlock(lockPool->lock);
+ return 0;
+ }
+
+ if(!(currentLockEntry->sem = ILSemaphoreCreate()))
+ {
+ ILMemPoolFree(&(lockPool->methodPool),
currentLockEntry);
+ ILMutexUnlock(lockPool->lock);
+ return 0;
+ }
+ /* We are using the support thread (ILThread) here to avoid */
+ /* blocking during execution of finalizers where the
ILExecThread */
+ /* for the same ILThread might change. */
+ currentLockEntry->thread = thread->supportThread;
+
+ currentLockEntry->method = method;
+ currentLockEntry->numWaitingThreads = 0;
+ currentLockEntry->userData = userData;
+ currentLockEntry->nextEntry = lockPool->lastLockedMethod;
+ lockPool->lastLockedMethod = currentLockEntry;
+
+ ILMutexUnlock(lockPool->lock);
+
+ /* Return with success. */
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * Unlock a locked method.
+ */
+static void *_ILMethodLockPool_UnlockMethod(ILMethodLockPool *lockPool,
+
ILMethod *method)
+{
+ if(lockPool)
+ {
+ ILMethodLockEntry *currentLockEntry =
lockPool->lastLockedMethod;
+
+ if(currentLockEntry)
+ {
+ /* Lock the lock pool. */
+ ILMutexLock(lockPool->lock);
+
+ currentLockEntry = lockPool->lastLockedMethod;
+
+ if(currentLockEntry)
+ {
+ if(currentLockEntry->method == method)
+ {
+ lockPool->lastLockedMethod =
currentLockEntry->nextEntry;
+ }
+ else
+ {
+ ILMethodLockEntry *tempLockEntry;
+
+ while(currentLockEntry)
+ {
+
if((currentLockEntry->nextEntry) &&
+
(currentLockEntry->nextEntry->method == method))
+ {
+ tempLockEntry =
currentLockEntry->nextEntry;
+
currentLockEntry->nextEntry = currentLockEntry->nextEntry->nextEntry;
+ currentLockEntry =
tempLockEntry;
+ break;
+ }
+ currentLockEntry =
currentLockEntry->nextEntry;
+ }
+ }
+ if(currentLockEntry)
+ {
+ /* We found the lock entry for the
given method and */
+ /* unlinked it from the list. */
+ /* So the locked method can't be found
by any other */
+ /* thread now. */
+
+ void *userData =
currentLockEntry->userData;
+
+ if(currentLockEntry->numWaitingThreads
== 0)
+ {
+ /* There are no threads waiting
for thie method. */
+ /* So we have to destroy the
lock entry here. */
+
+
_ILMethodLockEntry_Destroy(lockPool, currentLockEntry);
+ }
+ else
+ {
+ /* Release all threads waiting
for this method. */
+
ILSemaphorePostMultiple(currentLockEntry->sem,
+
currentLockEntry->numWaitingThreads);
+ }
+ /* Unlock the lock pool. */
+ ILMutexUnlock(lockPool->lock);
+
+ return userData;
+ }
+ }
+
+ /* Unlock the lock pool. */
+ ILMutexUnlock(lockPool->lock);
+ }
+ }
+ return 0;
+}
+
+/*
+ * Check if a method is locked and block the calling thread if the method is
+ * locked by an other thread.
+ * If the method is locked by the current thread the userData entry of the
+ * lock entry is returned.
+ * Returns 0 if the method is not locked,
+ */
+void *ILMethodLockPool_HandleLockedMethod(ILMethodLockPool *lockPool,
+
ILMethod *method,
+
ILCCtorMgr *cctorMgr)
+{
+ if(lockPool)
+ {
+ ILMethodLockEntry *currentLockEntry =
lockPool->lastLockedMethod;
+
+ if(currentLockEntry)
+ {
+ /* Lock the lock pool. */
+ ILMutexLock(lockPool->lock);
+
+ currentLockEntry = lockPool->lastLockedMethod;
+
+ while(currentLockEntry)
+ {
+ if(currentLockEntry->method == method)
+ {
+ break;
+ }
+ currentLockEntry = currentLockEntry->nextEntry;
+ }
+ if(currentLockEntry)
+ {
+ /* The method is locked. */
+ ILExecThread *thread = ILExecThreadCurrent();
+
+ if(currentLockEntry->thread ==
thread->supportThread)
+ {
+ /* The current thread locked the
method. */
+
+ /* Unlock the lock pool. */
+ ILMutexUnlock(lockPool->lock);
+
+ /* And return the userData entry. */
+ return currentLockEntry->userData;
+ }
+ else if(cctorMgr->thread ==
thread->supportThread)
+ {
+ /* We have to run the cctors queued for
this method. */
+ /* TODO */
+
+ /* Unlock the lock pool. */
+ ILMutexUnlock(lockPool->lock);
+
+ /* And return the userData entry. */
+ return currentLockEntry->userData;
+ }
+ else
+ {
+ ILExecProcess *process =
((ILClassPrivate *)(ILMethod_Owner(method)->userData))->process;
+
+ /* Increase the number of waiting
threads. */
+ ++(currentLockEntry->numWaitingThreads);
+
+ /* Unlock the lock pool. */
+ ILMutexUnlock(lockPool->lock);
+
+ /* Unlock the metadata. */
+ METADATA_UNLOCK(process);
+
+ /* And wait at the semaphore object. */
+ ILSemaphoreWait(currentLockEntry->sem);
+
+ /* Lock the metadata again. */
+ METADATA_WRLOCK(process);
+
+ /* Lock the lock pool again. */
+ ILMutexLock(lockPool->lock);
+
+ /* Decrease the number of waiting
threads. */
+ --(currentLockEntry->numWaitingThreads);
+
+ if(currentLockEntry->numWaitingThreads
== 0)
+ {
+ /* This is the last thread
waiting for this method. */
+ void *userData =
currentLockEntry->userData;
+
+
_ILMethodLockEntry_Destroy(lockPool, currentLockEntry);
+
+ /* Unlock the lock pool. */
+ ILMutexUnlock(lockPool->lock);
+
+ return userData;
+ }
+ else
+ {
+ /* Unlock the lock pool. */
+ ILMutexUnlock(lockPool->lock);
+
+ return
currentLockEntry->userData;
+ }
+ }
+ }
+ /* Unlock the lock pool. */
+ ILMutexUnlock(lockPool->lock);
+ }
+ }
+ return 0;
+}
+
/*
* Get the number of queued cctors.
*/
@@ -243,8 +545,18 @@
{
return 0;
}
+
+ if(!_ILMethodLockPool_Init(&(cctorMgr->lockPool)))
+ {
+ ILMutexDestroy(cctorMgr->lock);
+ return 0;
+ }
+
cctorMgr->thread = (ILThread *)0;;
cctorMgr->currentMethod = (ILMethod *)0;
+ #ifdef IL_USE_JIT
+ cctorMgr->currentJitFunction = 0;
+ #endif /* IL_USE_JIT */
cctorMgr->isStaticConstructor = 0;
cctorMgr->isConstructor = 0;
@@ -255,6 +567,7 @@
sizeof(ILClassEntry),
numCCtorEntries);
+
return 1;
}
return 0;
@@ -269,6 +582,8 @@
{
ILMemPoolDestroy(&(cctorMgr->classPool));
+ _ILMethodLockPool_Destroy(&(cctorMgr->lockPool));
+
if(cctorMgr->lock)
{
/* Destroy the lock mutex. */
@@ -278,6 +593,19 @@
}
/*
+ * Handle locked methods.
+ * Returns the userData of the locked method if the method is locked and
+ * 0 if the method isn't locked.
+ */
+void *ILCCtorMgr_HandleLockedMethod(ILCCtorMgr *cctorMgr,
+
ILMethod *method)
+{
+ return ILMethodLockPool_HandleLockedMethod(&(cctorMgr->lockPool),
+
method,
+
cctorMgr);
+}
+
+/*
* Set the current method to be compiled.
* This checks if the class initializer of the class owning the method has
* to be executed prior to executing the method.
@@ -287,6 +615,10 @@
{
if(cctorMgr)
{
+ #ifdef IL_USE_JIT
+ cctorMgr->currentJitFunction = 0;
+ #endif /* IL_USE_JIT */
+
if(method)
{
ILClass *methodOwner = ILMethod_Owner(method);
@@ -476,7 +808,7 @@
/*
* Run the queued cctors.
*/
-int ILCCtorMgr_RunCCtors(ILCCtorMgr *cctorMgr)
+int ILCCtorMgr_RunCCtors(ILCCtorMgr *cctorMgr, void *userData)
{
if(cctorMgr)
{
@@ -485,14 +817,29 @@
if(!(cctorMgr->lastClass))
{
/* There are no cctors queued. */
- /* So unlock the metadata. */
- METADATA_UNLOCK(thread);
+
+ /* So store the userdata where the coder expects it to
be. */
+ #ifdef IL_USE_CVM
+ cctorMgr->currentMethod->userData = userData;
+ #endif /* IL_USE_CVM */
+ #ifdef IL_USE_JIT
+ jit_function_setup_entry(cctorMgr->currentJitFunction,
userData);
+ #endif /* IL_USE_JIT */
+
+ /* Unlock the metadata. */
+ METADATA_UNLOCK(_ILExecThreadProcess(thread));
+
/* and return with success. */
return 1;
}
else
{
int result;
+ ILMethod *currentMethod = cctorMgr->currentMethod;
+ #ifdef IL_USE_JIT
+ ILJitFunction currentJitFunction =
cctorMgr->currentJitFunction;
+ #endif /* IL_USE_JIT */
+
ILInt32 numQueuedCCtors =
_ILCCtorMgr_GetNumQueuedCCtors(cctorMgr);
ILClass *classes[numQueuedCCtors];
ILClassEntry *classEntry = cctorMgr->lastClass;
@@ -509,8 +856,20 @@
cctorMgr->lastClass = (ILClassEntry *)0;
ILMemPoolClear(&(cctorMgr->classPool));
+ /* Lock the method. */
+ if(!_ILMethodLockPool_LockMethod(&(cctorMgr->lockPool),
+
currentMethod,
+
userData))
+ {
+ /* Unlock the metadata. */
+ METADATA_UNLOCK(_ILExecThreadProcess(thread));
+
+ /* and return with failure. */
+ return 0;
+ }
+
/* Now unlock the metadata. */
- METADATA_UNLOCK(thread);
+ METADATA_UNLOCK(_ILExecThreadProcess(thread));
if(cctorMgr->thread == thread->supportThread)
{
@@ -538,6 +897,26 @@
/* and unlock the cctor manager. */
ILMutexUnlock(cctorMgr->lock);
}
+
+ /* Lock the metadata again. */
+ IL_METADATA_WRLOCK(_ILExecThreadProcess(thread));
+
+ /* Store the userdata where the coder expects it to be.
*/
+ #ifdef IL_USE_CVM
+ currentMethod->userData = userData;
+ #endif /* IL_USE_CVM */
+ #ifdef IL_USE_JIT
+ jit_function_setup_entry(currentJitFunction, userData);
+ #endif /* IL_USE_JIT */
+
+ /* Unlock the method. */
+ _ILMethodLockPool_UnlockMethod(&(cctorMgr->lockPool),
+
currentMethod);
+
+
+ /* Unlock the metadata. */
+ IL_METADATA_UNLOCK(_ILExecThreadProcess(thread));
+
if(!result)
{
_ILCCtorMgr_ThrowTypeInitializationException(thread);
Index: engine/cctormgr.h
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnet/engine/cctormgr.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- engine/cctormgr.h 21 Jan 2007 17:53:29 -0000 1.2
+++ engine/cctormgr.h 11 Feb 2007 14:34:32 -0000 1.3
@@ -22,13 +22,16 @@
#define _ENGINE_CCTORMGR_H
#include "engine_private.h"
-
+#ifdef IL_USE_JIT
+#include "jitc.h"
+#endif /* IL_USE_JIT */
#ifdef __cplusplus
extern "C" {
#endif
/* Forward declarations. */
+typedef struct _tagILMethodLockEntry ILMethodLockEntry;
typedef struct _tagILClassEntry ILClassEntry;
typedef struct _tagILCCtorMgr ILCCtorMgr;
@@ -38,6 +41,46 @@
ILClassEntry *prevClass; /* The previous class entry. */
};
+/*
+ * Entry for one locked method.
+ */
+struct _tagILMethodLockEntry
+{
+ /* The next lock entryin the lock pool. */
+ ILMethodLockEntry *nextEntry;;
+
+ /* The locked method. */
+ ILMethod *method;
+
+ /* The thread that created the method lock entry. */
+ ILThread *thread;
+
+ /* The semaphore where the other threads are waiting. */
+ ILSemaphore *sem;
+
+ /* The number of waiting threads. */
+ ILInt32 numWaitingThreads;
+
+ /* Slot for private use data. */
+ void *userData;
+};
+
+/*
+ * The memory pool to hold the locked methods.
+ */
+typedef struct
+{
+ /* Mutex to synchronize the access to the lock pool. */
+ ILMutex *lock;
+
+ /* Memory pool to hold the locked methods. */
+ ILMemPool methodPool;
+
+
+ /* The first currently locked method in the lock pool. */
+ ILMethodLockEntry *lastLockedMethod;
+} ILMethodLockPool;
+
struct _tagILCCtorMgr
{
/* Mutex to synchronize the cctor execution. */
@@ -48,6 +91,12 @@
/* The currently compiled method. */
ILMethod *currentMethod;
+
+#ifdef IL_USE_JIT
+ /* The currentty compiled jit function. */
+ ILJitFunction currentJitFunction;
+#endif /* IL_USE_JIT */
+
/* Flag if the current method is a cctor. */
int isStaticConstructor : 1;
/* Flag if the current method is a ctor. */
@@ -58,6 +107,8 @@
/* The last classentry in the memory pool. */
ILClassEntry *lastClass;
+ /* The memory pool to hold the currently locked methods. */
+ ILMethodLockPool lockPool;
};
int ILCCtorMgr_Init(ILCCtorMgr *cctorMgr,
@@ -66,6 +117,13 @@
void ILCCtorMgr_Destroy(ILCCtorMgr *cctorMgr);
/*
+ * Handle locked methods.
+ * Returns the userData of the locked method if the method is locked and
+ * 0 if the method isn't locked.
+ */
+void *ILCCtorMgr_HandleLockedMethod(ILCCtorMgr *cctorMgr,
+
ILMethod *method);
+/*
* Set the current method to be compiled.
* This checks if the class initializer of the class owning the method has
* to be executed prior to executing the method.
@@ -113,9 +171,11 @@
/*
* Run the queued cctors.
+ * The userData is stored in the locked function and is returned
+ * by the call to ILCCtorMgr_HandleLockedMethod.
* Returns != 0 on success or 0 if an exception was thrown.
*/
-int ILCCtorMgr_RunCCtors(ILCCtorMgr *cctorMgr);
+int ILCCtorMgr_RunCCtors(ILCCtorMgr *cctorMgr, void *userData);
#ifdef __cplusplus
};
Index: engine/convert.c
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnet/engine/convert.c,v
retrieving revision 1.28
retrieving revision 1.29
diff -u -b -r1.28 -r1.29
--- engine/convert.c 16 Jan 2007 06:46:08 -0000 1.28
+++ engine/convert.c 11 Feb 2007 14:34:32 -0000 1.29
@@ -87,18 +87,13 @@
method is written in IL or not */
if(code.code)
{
- /* 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))
{
- METADATA_UNLOCK(thread);
*errorCode = IL_CONVERT_VERIFY_FAILED;
return 0;
}
- /* Run the needed cctors and unlock the metadata too */
- ILCoderRunCCtors(coder);
}
else
{
@@ -191,6 +186,14 @@
/* We need the metadata write lock */
METADATA_WRLOCK(thread);
+ /* Handle locked methods while cctors are executed. */
+ if((start = (unsigned char *)ILCoderHandleLockedMethod(coder, method)))
+ {
+ METADATA_UNLOCK(thread);
+ *errorCode = IL_CONVERT_OK;
+ return start;
+ }
+
/* Is the method already converted? */
if((start = (unsigned char *)(method->userData)) != 0)
{
@@ -504,12 +507,8 @@
}
/* The method is converted now */
- /* store the method pointer in a safe way so we can use a shortcut
macro */
- ILThreadAtomicStart();
- method->userData = (void *)start;
- ILThreadAtomicEnd();
/* Run the needed cctors and unlock the metadata too */
- ILCoderRunCCtors(coder);
+ ILCoderRunCCtors(coder, start);
*errorCode = IL_CONVERT_OK;
return start;
}
Index: engine/cvmc.c
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnet/engine/cvmc.c,v
retrieving revision 1.52
retrieving revision 1.53
diff -u -b -r1.52 -r1.53
--- engine/cvmc.c 23 Jan 2007 19:49:01 -0000 1.52
+++ engine/cvmc.c 11 Feb 2007 14:34:32 -0000 1.53
@@ -288,10 +288,10 @@
/*
* Run the class initializers queued during generation of the last method.
*/
-static ILInt32 CVMCoder_RunCCtors(ILCoder *_coder)
+static ILInt32 CVMCoder_RunCCtors(ILCoder *_coder, void *userData)
{
ILCVMCoder *coder = (ILCVMCoder *)_coder;
- return ILCCtorMgr_RunCCtors(&(coder->cctorMgr));
+ return ILCCtorMgr_RunCCtors(&(coder->cctorMgr), userData);
}
/*
@@ -304,6 +304,15 @@
}
/*
+ * Handle the method lock while running class initializers.
+ */
+static void *CVMCoder_HandleLockedMethod(ILCoder *_coder, ILMethod *method)
+{
+ ILCVMCoder *coder = (ILCVMCoder *)_coder;
+ return ILCCtorMgr_HandleLockedMethod(&(coder->cctorMgr), method);
+}
+
+/*
* Get a block of method cache memory for use in code unrolling.
*/
int _ILCVMStartUnrollBlock(ILCoder *_coder, int align, ILCachePosn *posn)
@@ -513,6 +522,7 @@
CVMCoder_ConvertCustom,
CVMCoder_RunCCtors,
CVMCoder_RunCCtor,
+ CVMCoder_HandleLockedMethod,
"sentinel"
};
Index: engine/cvmc_call.c
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnet/engine/cvmc_call.c,v
retrieving revision 1.36
retrieving revision 1.37
diff -u -b -r1.36 -r1.37
--- engine/cvmc_call.c 21 Jan 2007 17:53:29 -0000 1.36
+++ engine/cvmc_call.c 11 Feb 2007 14:34:32 -0000 1.37
@@ -497,11 +497,6 @@
static void CVMCoder_LoadFuncAddr(ILCoder *coder, ILMethod *methodInfo)
{
- /* Queue the cctor to run. */
- /* TODO: leave this one because the methodpointer might be used to
start */
- /* a new thread. This makes sure that the class of the thread start */
- /* function is initialized. */
- ILCCtorMgr_OnCallMethod(&(((ILCVMCoder *)coder)->cctorMgr), methodInfo);
CVMP_OUT_PTR(COP_PREFIX_LDFTN, methodInfo);
CVM_ADJUST(1);
}
Index: engine/jitc.c
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnet/engine/jitc.c,v
retrieving revision 1.67
retrieving revision 1.68
diff -u -b -r1.67 -r1.68
--- engine/jitc.c 23 Jan 2007 19:49:02 -0000 1.67
+++ engine/jitc.c 11 Feb 2007 14:34:32 -0000 1.68
@@ -74,11 +74,6 @@
/* #define _IL_JIT_ENABLE_INLINE 1 */
/*
- * To enable the cctor manager uncomment define the following define.
- */
-#define IL_JIT_ENABLE_CCTORMGR
-
-/*
* Acquire and release the metadata lock, while suppressing finalizers
* Must be kept in sync with convert.c
*/
@@ -334,6 +329,11 @@
#endif
/*
+ * Handle locked methods in the jit coder.
+ */
+static void *JITCoder_HandleLockedMethod(ILCoder *coder, ILMethod *method);
+
+/*
* Forward declaration of the JIT coder's instance block.
*/
typedef struct _tagILJITCoder ILJITCoder;
@@ -415,9 +415,6 @@
ILExecProcess *process;
jit_context_t context;
-#ifndef IL_JIT_ENABLE_CCTORMGR
- ILMethod *currentMethod;
-#endif /* !IL_JIT_ENABLE_CCTORMGR */
int debugEnabled;
int flags;
@@ -1966,64 +1963,6 @@
return((ILUInt32)jit_type_get_size(classPrivate->jitTypes.jitTypeBase));
}
-#ifndef IL_JIT_ENABLE_CCTORMGR
-/*
- * Call the static constructor for a class if necessary.
- */
-static void _ILJitCallStaticConstructor(ILJITCoder *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 != coder->currentMethod)
- {
- /* Output a call to the static constructor */
- #ifdef IL_JIT_THREAD_IN_SIGNATURE
- jit_value_t thread =
_ILJitCoderGetThread(coder);
-
- jit_insn_call(coder->jitFunction, "cctor",
-
ILJitFunctionFromILMethod(cctor), 0,
- &thread, 1, 0);
- #else
- jit_insn_call(coder->jitFunction, "cctor",
-
ILJitFunctionFromILMethod(cctor), 0,
- 0, 0, 0);
- #endif
- }
- }
- 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;
- }
- }
-}
-#endif /* !IL_JIT_ENABLE_CCTORMGR */
-
/*
* The exception handler which converts libjit inbuilt exceptions
* into clr exceptions.
@@ -2123,6 +2062,123 @@
}
/*
+ * The on demand driver function for libjit.
+ */
+static void *_ILJitOnDemandDriver(ILJitFunction func)
+{
+#if !defined(IL_CONFIG_REDUCE_CODE) && !defined(IL_WITHOUT_TOOLS) &&
defined(_IL_JIT_ENABLE_DEBUG)
+ char *methodName = _ILJitFunctionGetMethodName(func);
+#endif
+ ILMethod *method = (ILMethod *)jit_function_get_meta(func,
IL_JIT_META_METHOD);
+ ILClass *info = ILMethod_Owner(method);
+ ILClassPrivate *classPrivate = (ILClassPrivate *)info->userData;
+ ILExecProcess *process = classPrivate->process;
+ ILJITCoder *jitCoder = (ILJITCoder *)process->coder;
+ void *entry_point;
+ jit_on_demand_func onDemandCompiler;
+ int result = JIT_RESULT_OK;
+ jit_context_t context = jit_function_get_context(func);
+
+ if(!context)
+ {
+ result = JIT_RESULT_COMPILE_ERROR;
+ jit_exception_builtin(result);
+ }
+
+ /* Lock the metadata. */
+ METADATA_WRLOCK(process);
+
+ /* Handle a locked method. */
+ if((entry_point = JITCoder_HandleLockedMethod(process->coder, method)))
+ {
+ /* Unlock the metadata. */
+ METADATA_UNLOCK(process);
+
+ return entry_point;
+ }
+
+ /* Set the function info in the jit coder. */
+ jitCoder->jitFunction = func;
+ ILCCtorMgr_SetCurrentMethod(&(jitCoder->cctorMgr), method);
+ jitCoder->cctorMgr.currentJitFunction = func;
+
+ /* Lock down the context. */
+ jit_context_build_start(context);
+
+ if(!(onDemandCompiler = jit_function_get_on_demand_compiler(func)))
+ {
+ result = JIT_RESULT_COMPILE_ERROR;
+
+ /* Unlock the context. */
+ jit_context_build_end(context);
+
+ /* Unlock the metadata. */
+ METADATA_UNLOCK(process);
+
+ /* And throw an exception. */
+ jit_exception_builtin(result);
+ }
+
+ if((result = (*onDemandCompiler)(func)) == JIT_RESULT_OK)
+ {
+ #if !defined(IL_CONFIG_REDUCE_CODE) && !defined(IL_WITHOUT_TOOLS) &&
defined(_IL_JIT_ENABLE_DEBUG)
+ #ifdef _IL_JIT_DUMP_FUNCTION
+ if(jitCoder->flags & IL_CODER_FLAG_STATS)
+ {
+ ILMutexLock(globalTraceMutex);
+ jit_dump_function(stdout, func, methodName);
+ ILMutexUnlock(globalTraceMutex);
+ }
+ #endif /* _IL_JIT_DUMP_FUNCTION */
+ #endif
+
+ /* Now compile the function to it's native form. */
+ if(!jit_function_compile_entry(func, &entry_point))
+ {
+ /* How are errors handled ? */
+
+ /* Unlock the context. */
+ jit_context_build_end(context);
+
+ /* Unlock the metadata. */
+ METADATA_UNLOCK(process);
+
+ /* And throw an exception. */
+ jit_exception_builtin(JIT_RESULT_OUT_OF_MEMORY);
+ }
+
+ /* Unlock the context. */
+ jit_context_build_end(context);
+
+ /* and run the queued class initializers. */
+ ILCCtorMgr_RunCCtors(&(jitCoder->cctorMgr), entry_point);
+
+ #if !defined(IL_CONFIG_REDUCE_CODE) && !defined(IL_WITHOUT_TOOLS) &&
defined(_IL_JIT_ENABLE_DEBUG)
+ #ifdef _IL_JIT_DISASSEMBLE_FUNCTION
+ if(jitCoder->flags & IL_CODER_FLAG_STATS)
+ {
+ ILMutexLock(globalTraceMutex);
+ jit_dump_function(stdout, func, methodName);
+ ILMutexUnlock(globalTraceMutex);
+ }
+ #endif /* _IL_JIT_DISASSEMBLE_FUNCTION */
+ #endif
+ }
+ else
+ {
+ /* Unlock the context. */
+ jit_context_build_end(context);
+
+ /* Unlock the metadata. */
+ METADATA_UNLOCK(process);
+
+ /* And throw an exception. */
+ jit_exception_builtin(result);
+ }
+ return entry_point;
+}
+
+/*
* Initialize the libjit coder.
* Returns 1 on success and 0 on failure.
*/
@@ -2447,6 +2503,7 @@
return 1;
}
+
/*
* Create a new JIT coder instance.
*/
@@ -2481,6 +2538,10 @@
return 0;
}
+ /* Set the on demand compilation driver for this context. */
+ jit_context_set_on_demand_driver(coder->context,
+
_ILJitOnDemandDriver);
+
#ifndef IL_JIT_THREAD_IN_SIGNATURE
coder->thread = 0;
#endif
@@ -2744,11 +2805,7 @@
{
/* Mark breakpoint that reports current ILMethod and IL offset
*/
jit_insn_mark_breakpoint(jitCoder->jitFunction,
- #ifdef IL_JIT_ENABLE_CCTORMGR
(jit_nint)
ILCCtorMgr_GetCurrentMethod(&(jitCoder->cctorMgr)),
- #else /* !IL_JIT_ENABLE_CCTORMGR */
- (jit_nint)
jitCoder->currentMethod,
- #endif /* !IL_JIT_ENABLE_CCTORMGR */
(jit_nint)
offset);
}
#endif
@@ -2757,18 +2814,11 @@
/*
* Run the class initializers queued during generation of the last method.
*/
-static ILInt32 JITCoder_RunCCtors(ILCoder *coder)
+static ILInt32 JITCoder_RunCCtors(ILCoder *coder, void *userData)
{
-#ifdef IL_JIT_ENABLE_CCTORMGR
ILJITCoder *jitCoder = _ILCoderToILJITCoder(coder);
- return ILCCtorMgr_RunCCtors(&(jitCoder->cctorMgr));
-#else /* !IL_JIT_ENABLE_CCTORMGR */
- ILExecThread *thread = ILExecThreadCurrent();
-
- METADATA_UNLOCK(_ILExecThreadProcess(thread));
- return 1;
-#endif /* !IL_JIT_ENABLE_CCTORMGR */
+ return ILCCtorMgr_RunCCtors(&(jitCoder->cctorMgr), userData);;
}
/*
@@ -2781,6 +2831,16 @@
return ILCCtorMgr_RunCCtor(&(jitCoder->cctorMgr), classInfo);
}
+/*
+ * Handle the method lock while running class initializers.
+ */
+static void *JITCoder_HandleLockedMethod(ILCoder *coder, ILMethod *method)
+{
+ ILJITCoder *jitCoder = _ILCoderToILJITCoder(coder);
+
+ return ILCCtorMgr_HandleLockedMethod(&(jitCoder->cctorMgr), method);
+}
+
#ifdef IL_CONFIG_PINVOKE
/*
@@ -3085,7 +3145,7 @@
static int _ILJitCompileInternal(ILJitFunction func)
{
ILMethod *method = (ILMethod *)jit_function_get_meta(func,
IL_JIT_META_METHOD);
-#if (!defined(IL_CONFIG_REDUCE_CODE) && !defined(IL_WITHOUT_TOOLS) &&
defined(_IL_JIT_ENABLE_DEBUG)) || defined(IL_JIT_ENABLE_CCTORMGR)
+#if !defined(IL_CONFIG_REDUCE_CODE) && !defined(IL_WITHOUT_TOOLS) &&
defined(_IL_JIT_ENABLE_DEBUG)
ILClassPrivate *classPrivate = (ILClassPrivate
*)(ILMethod_Owner(method)->userData);
ILJITCoder *jitCoder = (ILJITCoder *)(classPrivate->process->coder);
#endif
@@ -3113,12 +3173,6 @@
}
#endif
-#ifdef IL_JIT_ENABLE_CCTORMGR
- METADATA_WRLOCK(jitCoder->process);
- jitCoder->jitFunction = func;
- ILCCtorMgr_SetCurrentMethod(&(jitCoder->cctorMgr), method);
-#endif /* IL_JIT_ENABLE_CCTORMGR */
-
#ifdef IL_JIT_THREAD_IN_SIGNATURE
for(current = 1; current < numParams; ++current)
{
@@ -3146,28 +3200,6 @@
#endif
jit_insn_return(func, returnValue);
-#if !defined(IL_CONFIG_REDUCE_CODE) && !defined(IL_WITHOUT_TOOLS) &&
defined(_IL_JIT_ENABLE_DEBUG)
-#ifdef _IL_JIT_DUMP_FUNCTION
- if(jitCoder->flags & IL_CODER_FLAG_STATS)
- {
- ILMutexLock(globalTraceMutex);
- jit_dump_function(stdout, func, methodName);
- ILMutexUnlock(globalTraceMutex);
- }
-#endif
-#ifdef _IL_JIT_DISASSEMBLE_FUNCTION
- if(jitCoder->flags & IL_CODER_FLAG_STATS)
- {
- if(!jit_function_compile(func))
- {
- return IL_CODER_END_TOO_BIG;
- }
- ILMutexLock(globalTraceMutex);
- jit_dump_function(stdout, func, methodName);
- ILMutexUnlock(globalTraceMutex);
- }
-#endif
-#endif
return JIT_RESULT_OK;
}
@@ -4567,6 +4599,7 @@
JITCoder_ConvertCustom,
JITCoder_RunCCtors,
JITCoder_RunCCtor,
+ JITCoder_HandleLockedMethod,
"sentinel"
};
#ifdef __cplusplus
Index: engine/jitc_call.c
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnet/engine/jitc_call.c,v
retrieving revision 1.37
retrieving revision 1.38
diff -u -b -r1.37 -r1.38
--- engine/jitc_call.c 23 Jan 2007 19:49:02 -0000 1.37
+++ engine/jitc_call.c 11 Feb 2007 14:34:32 -0000 1.38
@@ -480,10 +480,6 @@
ILMutexUnlock(globalTraceMutex);
}
#endif
-#ifndef 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);
@@ -516,6 +512,8 @@
#endif
/* Call the engine function directly with the supplied args. */
+ /* Queue the cctor to run. */
+ ILCCtorMgr_OnCallMethod(&(jitCoder->cctorMgr), methodInfo);
#ifdef IL_JIT_THREAD_IN_SIGNATURE
destroyCallSignature = _ILJitFillArguments(jitCoder,
methodInfo,
@@ -824,16 +822,14 @@
type = ILType_FromClass(classInfo);
synType = ILClassGetSynType(classInfo);
-#ifndef 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)))
{
ILJitValue thread = _ILJitCoderGetThread(jitCoder);
+ /* Queue the cctor to run. */
+ ILCCtorMgr_OnCallMethod(&(jitCoder->cctorMgr), methodInfo);
+
/* Call the engine function directly with the supplied args. */
if(internalType == _IL_JIT_IMPL_INTERNALALLOC)
{
@@ -1704,11 +1700,7 @@
{
jit_insn_mark_breakpoint(jitCoder->jitFunction,
JIT_DEBUGGER_DATA1_METHOD_LEAVE,
- #ifdef IL_JIT_ENABLE_CCTORMGR
(jit_nint)
ILCCtorMgr_GetCurrentMethod(&(jitCoder->cctorMgr)));
- #else /* !IL_JIT_ENABLE_CCTORMGR */
- (jit_nint)
jitCoder->currentMethod);
- #endif /* !IL_JIT_ENABLE_CCTORMGR */
}
#endif
@@ -1790,13 +1782,6 @@
}
jitFunction = ILJitFunctionFromILMethod(methodInfo);
}
-#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 */
#ifndef IL_JIT_FNPTR_ILMETHOD
/* Get the vtable pointer for the function. */
function = jit_function_to_vtable_pointer(jitFunction);
Index: engine/jitc_except.c
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnet/engine/jitc_except.c,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -b -r1.15 -r1.16
--- engine/jitc_except.c 21 Jan 2007 17:53:29 -0000 1.15
+++ engine/jitc_except.c 11 Feb 2007 14:34:32 -0000 1.16
@@ -530,11 +530,7 @@
(jit_nint)classInfo);
ILJitValue method =
jit_value_create_nint_constant(jitCoder->jitFunction,
_IL_JIT_TYPE_VPTR,
-#ifdef IL_JIT_ENABLE_CCTORMGR
(jit_nint)ILCCtorMgr_GetCurrentMethod(&(jitCoder->cctorMgr)));
-#else /* !IL_JIT_ENABLE_CCTORMGR */
-
(jit_nint)jitCoder->currentMethod);
-#endif /* !IL_JIT_ENABLE_CCTORMGR */
ILJitValue nullException =
jit_value_create_nint_constant(jitCoder->jitFunction,
_IL_JIT_TYPE_VPTR,
(jit_nint)0);
Index: engine/jitc_inline.c
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnet/engine/jitc_inline.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -b -r1.3 -r1.4
--- engine/jitc_inline.c 21 Jan 2007 18:02:10 -0000 1.3
+++ engine/jitc_inline.c 11 Feb 2007 14:34:32 -0000 1.4
@@ -240,11 +240,7 @@
/* Now check if the method is allready somewhere in the
currently */
/* inlined methods to avoid an endless recursion. */
- #ifdef IL_JIT_ENABLE_CCTORMGR
if(method == ILCCtorMgr_GetCurrentMethod(&(jitCoder->cctorMgr)))
- #else /* !IL_JIT_ENABLE_CCTORMGR */
- if(method == jitCoder->currentMethod)
- #endif /* !IL_JIT_ENABLE_CCTORMGR */
{
return 0;
}
@@ -349,7 +345,6 @@
return 0;
}
- #ifdef IL_JIT_ENABLE_CCTORMGR
/* Queue the cctor to run. */
if(!ILCCtorMgr_OnCallMethod(&(jitCoder->cctorMgr), method))
{
@@ -357,7 +352,6 @@
_ILJitCoderInlineContextPop(jitCoder);
return 0;
}
- #endif /* IL_JIT_ENABLE_CCTORMGR */
ILMemPoolClear(&(inlineContext->labelPool));
inlineContext->labelList = 0;
Index: engine/jitc_obj.c
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnet/engine/jitc_obj.c,v
retrieving revision 1.27
retrieving revision 1.28
diff -u -b -r1.27 -r1.28
--- engine/jitc_obj.c 21 Jan 2007 17:53:29 -0000 1.27
+++ engine/jitc_obj.c 11 Feb 2007 14:34:32 -0000 1.28
@@ -301,11 +301,7 @@
{
args[0] = jit_value_create_nint_constant(jitCoder->jitFunction,
_IL_JIT_TYPE_VPTR,
-#ifdef IL_JIT_ENABLE_CCTORMGR
(jit_nint)ILCCtorMgr_GetCurrentMethod(&(jitCoder->cctorMgr)));
-#else /* !IL_JIT_ENABLE_CCTORMGR */
-
(jit_nint)jitCoder->currentMethod);
-#endif /* !IL_JIT_ENABLE_CCTORMGR */
args[1] = _ILJitStackItemValue(object);
args[2] = classTo;
returnValue = jit_insn_call_native(jitCoder->jitFunction,
@@ -436,13 +432,8 @@
#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))
@@ -577,13 +568,8 @@
}
#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)
@@ -707,13 +693,8 @@
/* 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_setup.c
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnet/engine/jitc_setup.c,v
retrieving revision 1.25
retrieving revision 1.26
diff -u -b -r1.25 -r1.26
--- engine/jitc_setup.c 23 Jan 2007 19:49:02 -0000 1.25
+++ engine/jitc_setup.c 11 Feb 2007 14:34:32 -0000 1.26
@@ -42,15 +42,6 @@
}
#endif /* _IL_JIT_ENABLE_INLINE */
- /* Record the current jitted function. */
- coder->jitFunction = ILJitFunctionFromILMethod(method);
- /* Record the current method. */
-#ifdef IL_JIT_ENABLE_CCTORMGR
- ILCCtorMgr_SetCurrentMethod(&(coder->cctorMgr), method);
-#else /* !IL_JIT_ENABLE_CCTORMGR */
- coder->currentMethod = method;
-#endif /* !IL_JIT_ENABLE_CCTORMGR */
-
#if !defined(IL_CONFIG_REDUCE_CODE) && !defined(IL_WITHOUT_TOOLS)
if (coder->flags & IL_CODER_FLAG_STATS)
{
@@ -71,47 +62,6 @@
}
#endif
-#ifndef IL_JIT_ENABLE_CCTORMGR
- if(ILMethod_IsStaticConstructor(method))
- {
- /* We have to take care that the method is executed only once.
*/
- ILClass *info;
- ILJitValue classInfo;
- ILJitValue cctorOnce;
- ILJitValue attributes;
- ILJitValue temp;
- jit_label_t startLabel = jit_label_undefined;
- jit_label_t endLabel = jit_label_undefined;
- jit_label_t label1 = jit_label_undefined;
-
- jit_insn_label(coder->jitFunction, &startLabel);
-
- info = ILMethod_Owner(method);
- classInfo = jit_value_create_nint_constant(coder->jitFunction,
-
_IL_JIT_TYPE_VPTR,
-
(jit_nint)info);
- cctorOnce = jit_value_create_nint_constant(coder->jitFunction,
-
_IL_JIT_TYPE_UINT32,
-
(jit_nint)IL_META_TYPEDEF_CCTOR_ONCE);
- attributes = jit_insn_load_relative(coder->jitFunction,
-
classInfo,
-
offsetof(ILClass, attributes),
-
_IL_JIT_TYPE_UINT32);
- temp = jit_insn_and(coder->jitFunction, attributes, cctorOnce);
- jit_insn_branch_if_not(coder->jitFunction, temp, &label1);
- jit_insn_return(coder->jitFunction, 0);
- jit_insn_label(coder->jitFunction, &label1);
- temp = jit_insn_or(coder->jitFunction, attributes, cctorOnce);
- jit_insn_store_relative(coder->jitFunction, classInfo,
-
offsetof(ILClass, attributes), temp);
-
- jit_insn_label(coder->jitFunction, &endLabel);
- /* Make sure that this check will remain very first even if any
- 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_CONFIG_DEBUGGER
/* Check if this method can be debugged */
debugger = ILDebuggerFromProcess(coder->process);
@@ -204,9 +154,6 @@
static int JITCoder_Finish(ILCoder *_coder)
{
ILJITCoder *jitCoder = ((ILJITCoder *)_coder);
-#if !defined(IL_CONFIG_REDUCE_CODE) && !defined(IL_WITHOUT_TOOLS) &&
defined(_IL_JIT_ENABLE_DEBUG)
- char *methodName = _ILJitFunctionGetMethodName(jitCoder->jitFunction);
-#endif
#ifdef _IL_JIT_ENABLE_INLINE
if(jitCoder->currentInlineContext)
@@ -230,36 +177,6 @@
}
jitCoder->labelOutOfMemory = 0;
-#if !defined(IL_CONFIG_REDUCE_CODE) && !defined(IL_WITHOUT_TOOLS) &&
defined(_IL_JIT_ENABLE_DEBUG)
-#ifdef _IL_JIT_DUMP_FUNCTION
- if(jitCoder->flags & IL_CODER_FLAG_STATS)
- {
- ILMutexLock(globalTraceMutex);
- jit_dump_function(stdout, jitCoder->jitFunction, methodName);
- ILMutexUnlock(globalTraceMutex);
- }
-#endif /* _IL_JIT_DUMP_FUNCTION */
-#endif
- if(!jit_function_compile(jitCoder->jitFunction))
- {
- return IL_CODER_END_TOO_BIG;
- }
-#if !defined(IL_CONFIG_REDUCE_CODE) && !defined(IL_WITHOUT_TOOLS) &&
defined(_IL_JIT_ENABLE_DEBUG)
-#ifdef _IL_JIT_DISASSEMBLE_FUNCTION
- if(jitCoder->flags & IL_CODER_FLAG_STATS)
- {
- ILMutexLock(globalTraceMutex);
- jit_dump_function(stdout, jitCoder->jitFunction, methodName);
- ILMutexUnlock(globalTraceMutex);
- }
-#endif /* _IL_JIT_DISASSEMBLE_FUNCTION */
-#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/null_coder.c
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnet/engine/null_coder.c,v
retrieving revision 1.28
retrieving revision 1.29
diff -u -b -r1.28 -r1.29
--- engine/null_coder.c 16 Jan 2007 06:46:08 -0000 1.28
+++ engine/null_coder.c 11 Feb 2007 14:34:32 -0000 1.29
@@ -418,7 +418,7 @@
void *customName, void
*customCookie)
{
}
-static ILInt32 Coder_RunCCtors(ILCoder *coder)
+static ILInt32 Coder_RunCCtors(ILCoder *coder, void *userData)
{
return 1;
}
@@ -426,6 +426,10 @@
{
return 1;
}
+static void *Coder_HandleLockedMethod(ILCoder *coder, ILMethod *method)
+{
+ return 0;
+}
/*
* Null coder class and instance.
@@ -538,6 +542,7 @@
Coder_ConvertCustom,
Coder_RunCCtors,
Coder_RunCCtor,
+ Coder_HandleLockedMethod,
"sentinel"
};
ILCoder _ILNullCoder = {&_ILNullCoderClass};
Index: include/il_coder.h
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnet/include/il_coder.h,v
retrieving revision 1.53
retrieving revision 1.54
diff -u -b -r1.53 -r1.54
--- include/il_coder.h 16 Jan 2007 06:46:08 -0000 1.53
+++ include/il_coder.h 11 Feb 2007 14:34:32 -0000 1.54
@@ -817,7 +817,7 @@
* The metadata lock must be still accuired and will be released just
* before the cctors are executed.
*/
- ILInt32 (*runCCtors)(ILCoder *coder);
+ ILInt32 (*runCCtors)(ILCoder *coder, void *userData);
/*
* Run the class initializer for the given class.
@@ -825,6 +825,18 @@
ILInt32 (*runCCtor)(ILCoder *coder, ILClass *classInfo);
/*
+ * Handle a locked method.
+ * If the current thread holds the method lock the userData supplied
when
+ * the method was locked is returned.
+ * If the current thread is currently executing class initializers the
+ * cctors of the method are executed and after they are finished the
+ * the userData supplied when the method was locked is returned.
+ * In the other case the thread is blocked until the method is unlocked
+ * and then the userData supplied when the method was locked is
returned.
+ */
+ void *(*handleLockedMethod)(ILCoder *coder, ILMethod *method);
+
+ /*
* Sentinel string to catch missing methods in class tables.
*/
const char *sentinel;
@@ -1103,10 +1115,12 @@
(customCookie)))
#define ILCoderMarkEnd(coder) \
((*((coder)->classInfo->markEnd))((coder)))
-#define ILCoderRunCCtors(coder) \
- ((*((coder)->classInfo->runCCtors))((coder)))
-#define ILCoderRunCCtor(coder, classInfo) \
- ((*((coder)->classInfo->runCCtor))((coder),(classInfo)))
+#define ILCoderRunCCtors(coder,userData) \
+ ((*((coder)->classInfo->runCCtors))((coder),
(userData)))
+#define ILCoderRunCCtor(coder,classInfo) \
+ ((*((coder)->classInfo->runCCtor))((coder),
(classInfo)))
+#define ILCoderHandleLockedMethod(coder,method) \
+ (*((coder)->classInfo->handleLockedMethod))((coder),
(method))
#ifdef __cplusplus
};
Index: include/il_thread.h
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnet/include/il_thread.h,v
retrieving revision 1.27
retrieving revision 1.28
diff -u -b -r1.27 -r1.28
--- include/il_thread.h 10 Oct 2005 20:03:15 -0000 1.27
+++ include/il_thread.h 11 Feb 2007 14:34:32 -0000 1.28
@@ -48,6 +48,7 @@
typedef struct _tagILThread ILThread;
typedef struct _tagILMutex ILMutex;
typedef struct _tagILRWLock ILRWLock;
+typedef struct _tagILSemaphore ILSemaphore;
typedef struct _tagILWaitHandle ILWaitHandle;
/*
@@ -399,6 +400,34 @@
void ILRWLockUnlock(ILRWLock *rwlock);
/*
+ * Create a semaphore. Note: this type of semaphore will not
+ * necessarily update the thread's "wait/sleep/join"
+ * state, so it isn't directly suitable for emulating
+ * Windows-like wait handle semaphores.
+ */
+ILSemaphore *ILSemaphoreCreate(void);
+
+/*
+ * Destroy a semaphore.
+ */
+void ILSemaphoreDestroy(ILSemaphore *sem);
+
+/*
+ * Wait on a semaphore.
+ */
+void ILSemaphoreWait(ILSemaphore *sem);
+
+/*
+ * Increase the semaphore count by 1.
+ */
+void ILSemaphorePost(ILSemaphore *sem);
+
+/*
+ * Increase the semaphore count by count.
+ */
+void ILSemaphorePostMultiple(ILSemaphore *sem, ILUInt32 count);
+
+/*
* Close a wait handle. Returns zero if the handle is
* currently owned by a thread.
*/
Index: support/Makefile.am
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnet/support/Makefile.am,v
retrieving revision 1.55
retrieving revision 1.56
diff -u -b -r1.55 -r1.56
--- support/Makefile.am 22 Aug 2005 12:39:20 -0000 1.55
+++ support/Makefile.am 11 Feb 2007 14:34:32 -0000 1.56
@@ -59,6 +59,7 @@
regex.c \
rem_float.c \
ripemd160.c \
+ semaphore.c \
serial.c \
sha1.c \
sha256.c \
Index: support/no_defs.h
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnet/support/no_defs.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -b -r1.4 -r1.5
--- support/no_defs.h 11 May 2004 08:41:19 -0000 1.4
+++ support/no_defs.h 11 Feb 2007 14:34:32 -0000 1.5
@@ -97,6 +97,7 @@
#define _ILSemaphoreDestroy(sem) do { ; } while (0)
#define _ILSemaphoreWait(sem) do { ; } while (0)
#define _ILSemaphorePost(sem) do { ; } while (0)
+#define _ILSemaphorePostMultiple(sem, count) do { ; } while (0)
/*
* Primitive condition variable operations.
Index: support/pt_defs.c
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnet/support/pt_defs.c,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -b -r1.9 -r1.10
--- support/pt_defs.c 4 Sep 2006 18:07:30 -0000 1.9
+++ support/pt_defs.c 11 Feb 2007 14:34:32 -0000 1.10
@@ -286,6 +286,28 @@
}
}
+/*
+ * Increase the semaphore count by count to release count threads waiting
+ * at the semaphore.
+ */
+int _ILSemaphorePostMultiple(_ILSemaphore *sem, ILUInt32 count)
+{
+ if((count > 0) && (count < IL_MAX_INT32))
+ {
+ ILUInt32 current;
+
+ for(current = 0; current < count; current++)
+ {
+ if(sem_post(sem))
+ {
+ return 0;
+ }
+ }
+ return 1;
+ }
+ return 0;
+}
+
#ifdef __cplusplus
};
#endif
Index: support/pt_defs.h
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnet/support/pt_defs.h,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -b -r1.10 -r1.11
--- support/pt_defs.h 4 Sep 2006 18:07:30 -0000 1.10
+++ support/pt_defs.h 11 Feb 2007 14:34:32 -0000 1.11
@@ -206,6 +206,7 @@
#define _ILSemaphoreDestroy(sem) (sem_destroy((sem)))
#define _ILSemaphoreWait(sem) (sem_wait((sem)))
#define _ILSemaphorePost(sem) (sem_post((sem)))
+int _ILSemaphorePostMultiple(_ILSemaphore *sem, ILUInt32 count);
/*
* Primitive condition variable operations.
Index: support/w32_defs.h
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnet/support/w32_defs.h,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -b -r1.8 -r1.9
--- support/w32_defs.h 16 Jun 2004 09:05:06 -0000 1.8
+++ support/w32_defs.h 11 Feb 2007 14:34:32 -0000 1.9
@@ -156,6 +156,10 @@
do { \
ReleaseSemaphore(*(sem), 1, NULL); \
} while (0)
+#define _ILSemaphorePostMultiple(sem, count) \
+ do { \
+ ReleaseSemaphore(*(sem), (count), NULL); \
+ } while (0)
/*
* Primitive condition variable operations.
Index: support/semaphore.c
===================================================================
RCS file: support/semaphore.c
diff -N support/semaphore.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ support/semaphore.c 11 Feb 2007 14:34:32 -0000 1.1
@@ -0,0 +1,68 @@
+/*
+ * semaphore.c - Semaphore management routines.
+ *
+ * Copyright (C) 2002 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
+ */
+
+/*
+
+Note: the code in this module is generic to all platforms. It implements
+the correct CLI locking semantics based on the primitives in "*_defs.h".
+You normally won't need to modify or replace this file when porting.
+
+*/
+
+#include "thr_defs.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ILSemaphore *ILSemaphoreCreate(void)
+{
+ _ILSemaphore *sem;
+ sem = (_ILSemaphore *)ILMalloc(sizeof(_ILSemaphore));
+ if(sem)
+ {
+ _ILSemaphoreCreate(sem);
+ }
+ return (ILSemaphore *)sem;
+}
+
+void ILSemaphoreDestroy(ILSemaphore *sem)
+{
+ _ILSemaphoreDestroy((_ILSemaphore *)sem);
+}
+
+void ILSemaphoreWait(ILSemaphore *sem)
+{
+ _ILSemaphoreWait((_ILSemaphore *)sem);
+}
+
+void ILSemaphorePost(ILSemaphore *sem)
+{
+ _ILSemaphorePost((_ILSemaphore *)sem);
+}
+
+void ILSemaphorePostMultiple(ILSemaphore *sem, ILUInt32 count)
+{
+ _ILSemaphorePostMultiple((_ILSemaphore *)sem, count);
+}
+
+#ifdef __cplusplus
+};
+#endif
- [dotgnu-pnet-commits] pnet ChangeLog engine/cctormgr.c engine/cctormg...,
Klaus Treichel <=