summaryrefslogtreecommitdiffstats
path: root/generic/tclInt.h
diff options
context:
space:
mode:
Diffstat (limited to 'generic/tclInt.h')
-rw-r--r--generic/tclInt.h310
1 files changed, 93 insertions, 217 deletions
diff --git a/generic/tclInt.h b/generic/tclInt.h
index 42e2212..45eaf7e 100644
--- a/generic/tclInt.h
+++ b/generic/tclInt.h
@@ -10,7 +10,7 @@
* Copyright (c) 2001, 2002 by Kevin B. Kenny. All rights reserved.
* Copyright (c) 2007 Daniel A. Steffen <das@users.sourceforge.net>
* Copyright (c) 2006-2008 by Joe Mistachkin. All rights reserved.
- * Copyright (c) 2008 by Miguel Sofer. All rights reserved.
+ * Copyright (c) 2008-2011 by Miguel Sofer. All rights reserved.
*
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -1390,13 +1390,6 @@ MODULE_SCOPE void TclThreadDataKeySet(Tcl_ThreadDataKey *keyPtr,
(ThreadSpecificData *)Tcl_GetThreadData((keyPtr), sizeof(ThreadSpecificData))
/*
- *----------------------------------------------------------------
- * Data structures related to bytecode compilation and execution. These are
- * used primarily in tclCompile.c, tclExecute.c, and tclBasic.c.
- *----------------------------------------------------------------
- */
-
-/*
* Forward declaration to prevent errors when the forward references to
* Tcl_Parse and CompileEnv are encountered in the procedure type CompileProc
* declared below.
@@ -1438,19 +1431,6 @@ typedef int (CompileHookProc)(Tcl_Interp *interp,
struct CompileEnv *compEnvPtr, ClientData clientData);
/*
- * The data structure for a (linked list of) execution stacks.
- */
-
-typedef struct ExecStack {
- struct ExecStack *prevPtr;
- struct ExecStack *nextPtr;
- Tcl_Obj **markerPtr;
- Tcl_Obj **endPtr;
- Tcl_Obj **tosPtr;
- Tcl_Obj *stackWords[1];
-} ExecStack;
-
-/*
* The data structure defining the execution environment for ByteCode's.
* There is one ExecEnv structure per Tcl interpreter. It holds the evaluation
* stack that holds command operands and results. The stack grows towards
@@ -1487,8 +1467,6 @@ typedef struct CoroutineData {
} CoroutineData;
typedef struct ExecEnv {
- ExecStack *execStackPtr; /* Points to the first item in the evaluation
- * stack on the heap. */
Tcl_Obj *constants[2]; /* Pointers to constant "0" and "1" objs. */
struct Tcl_Interp *interp;
struct NRE_callback *callbackPtr;
@@ -1769,24 +1747,6 @@ enum PkgPreferOptions {
/*
*----------------------------------------------------------------
- * This structure shadows the first few fields of the memory cache for the
- * allocator defined in tclThreadAlloc.c; it has to be kept in sync with the
- * definition there.
- * Some macros require knowledge of some fields in the struct in order to
- * avoid hitting the TSD unnecessarily. In order to facilitate this, a pointer
- * to the relevant fields is kept in the objCache field in struct Interp.
- *----------------------------------------------------------------
- */
-
-typedef struct AllocCache {
- struct Cache *nextPtr; /* Linked list of cache entries. */
- Tcl_ThreadId owner; /* Which thread's cache is this? */
- Tcl_Obj *firstObjPtr; /* List of free objects for thread. */
- int numObjects; /* Number of objects for thread. */
-} AllocCache;
-
-/*
- *----------------------------------------------------------------
* This structure defines an interpreter, which is a collection of commands
* plus other state information related to interpreting commands, such as
* variable storage. Primary responsibility for this data structure is in
@@ -2118,7 +2078,6 @@ typedef struct Interp {
* They are used by the macros defined below.
*/
- AllocCache *allocCache;
void *pendingObjDataPtr; /* Pointer to the Cache and PendingObjData
* structs for this interp's thread; see
* tclObj.c and tclThreadAlloc.c */
@@ -2351,17 +2310,6 @@ struct LimitHandler {
#define UCHAR(c) ((unsigned char) (c))
/*
- * This macro is used to properly align the memory allocated by Tcl, giving
- * the same alignment as the native malloc.
- */
-
-#if defined(__APPLE__)
-#define TCL_ALLOCALIGN 16
-#else
-#define TCL_ALLOCALIGN (2*sizeof(void *))
-#endif
-
-/*
* This macro is used to determine the offset needed to safely allocate any
* data structure in memory. Given a starting offset or size, it "rounds up"
* or "aligns" the offset to the next 8-byte boundary so that any data
@@ -2902,7 +2850,6 @@ MODULE_SCOPE void TclCreateLateExitHandler(Tcl_ExitProc *proc,
ClientData clientData);
MODULE_SCOPE void TclDeleteLateExitHandler(Tcl_ExitProc *proc,
ClientData clientData);
-MODULE_SCOPE void TclFinalizeAllocSubsystem(void);
MODULE_SCOPE void TclFinalizeAsync(void);
MODULE_SCOPE void TclFinalizeDoubleConversion(void);
MODULE_SCOPE void TclFinalizeEncodingSubsystem(void);
@@ -2919,7 +2866,6 @@ MODULE_SCOPE void TclFinalizeNotifier(void);
MODULE_SCOPE void TclFinalizeObjects(void);
MODULE_SCOPE void TclFinalizePreserve(void);
MODULE_SCOPE void TclFinalizeSynchronization(void);
-MODULE_SCOPE void TclFinalizeThreadAlloc(void);
MODULE_SCOPE void TclFinalizeThreadData(void);
MODULE_SCOPE void TclFinalizeThreadObjects(void);
MODULE_SCOPE double TclFloor(const mp_int *a);
@@ -3097,8 +3043,6 @@ MODULE_SCOPE void TclSetDuplicateObj(Tcl_Obj *dupPtr, Tcl_Obj *objPtr);
MODULE_SCOPE void TclSetProcessGlobalValue(ProcessGlobalValue *pgvPtr,
Tcl_Obj *newValue, Tcl_Encoding encoding);
MODULE_SCOPE void TclSignalExitThread(Tcl_ThreadId id, int result);
-MODULE_SCOPE void * TclStackRealloc(Tcl_Interp *interp, void *ptr,
- int numBytes);
MODULE_SCOPE int TclStringMatch(const char *str, int strLen,
const char *pattern, int ptnLen, int flags);
MODULE_SCOPE int TclStringMatchObj(Tcl_Obj *stringObj,
@@ -3808,10 +3752,10 @@ typedef const char *TclDTraceStr;
#endif /* TCL_COMPILE_STATS */
# define TclAllocObjStorage(objPtr) \
- TclAllocObjStorageEx(NULL, (objPtr))
+ (objPtr) = TclSmallAlloc()
# define TclFreeObjStorage(objPtr) \
- TclFreeObjStorageEx(NULL, (objPtr))
+ TclSmallFree(objPtr)
#ifndef TCL_MEM_DEBUG
# define TclNewObj(objPtr) \
@@ -3846,128 +3790,122 @@ typedef const char *TclDTraceStr;
} \
}
-#if defined(PURIFY)
+#else /* TCL_MEM_DEBUG */
+MODULE_SCOPE void TclDbInitNewObj(Tcl_Obj *objPtr, const char *file,
+ int line);
-/*
- * The PURIFY mode is like the regular mode, but instead of doing block
- * Tcl_Obj allocation and keeping a freed list for efficiency, it always
- * allocates and frees a single Tcl_Obj so that tools like Purify can better
- * track memory leaks.
- */
+# define TclDbNewObj(objPtr, file, line) \
+ do { \
+ TclIncrObjsAllocated(); \
+ (objPtr) = (Tcl_Obj *) \
+ Tcl_DbCkalloc(sizeof(Tcl_Obj), (file), (line)); \
+ TclDbInitNewObj((objPtr), (file), (line)); \
+ TCL_DTRACE_OBJ_CREATE(objPtr); \
+ } while (0)
-# define TclAllocObjStorageEx(interp, objPtr) \
- (objPtr) = (Tcl_Obj *) Tcl_Alloc(sizeof(Tcl_Obj))
+# define TclNewObj(objPtr) \
+ TclDbNewObj(objPtr, __FILE__, __LINE__);
-# define TclFreeObjStorageEx(interp, objPtr) \
- ckfree((char *) (objPtr))
+# define TclDecrRefCount(objPtr) \
+ Tcl_DbDecrRefCount(objPtr, __FILE__, __LINE__)
-#undef USE_THREAD_ALLOC
-#elif defined(TCL_THREADS) && defined(USE_THREAD_ALLOC)
+# define TclNewListObjDirect(objc, objv) \
+ TclDbNewListObjDirect(objc, objv, __FILE__, __LINE__)
+
+#endif /* TCL_MEM_DEBUG */
/*
+ * Macros that drive the allocator behaviour
+ */
+
+#if defined(TCL_THREADS)
+/*
* The TCL_THREADS mode is like the regular mode but allocates Tcl_Obj's from
* per-thread caches.
*/
-
-MODULE_SCOPE Tcl_Obj * TclThreadAllocObj(void);
-MODULE_SCOPE void TclThreadFreeObj(Tcl_Obj *);
-MODULE_SCOPE Tcl_Mutex *TclpNewAllocMutex(void);
-MODULE_SCOPE void TclFreeAllocCache(void *);
+MODULE_SCOPE void TclpFreeAllocCache(void *);
MODULE_SCOPE void * TclpGetAllocCache(void);
MODULE_SCOPE void TclpSetAllocCache(void *);
+MODULE_SCOPE void TclFreeAllocCache(void *);
MODULE_SCOPE void TclpFreeAllocMutex(Tcl_Mutex *mutex);
-MODULE_SCOPE void TclpFreeAllocCache(void *);
+MODULE_SCOPE Tcl_Mutex *TclpNewAllocMutex(void);
+#endif
/*
- * These macros need to be kept in sync with the code of TclThreadAllocObj()
- * and TclThreadFreeObj().
- *
- * Note that the optimiser should resolve the case (interp==NULL) at compile
- * time.
+ * List of valid allocators. Have to respect the following convention:
+ * - allocators that shunt TclpAlloc to malloc are below aNONE
+ * - allocators that use zippy are above aNONE
*/
-# define ALLOC_NOBJHIGH 1200
+#define aNATIVE 0
+#define aPURIFY 1
+#define aNONE 2
+#define aZIPPY 3
+#define aMULTI 4
-# define TclAllocObjStorageEx(interp, objPtr) \
- do { \
- AllocCache *cachePtr; \
- if (((interp) == NULL) || \
- ((cachePtr = ((Interp *)(interp))->allocCache), \
- (cachePtr->numObjects == 0))) { \
- (objPtr) = TclThreadAllocObj(); \
- } else { \
- (objPtr) = cachePtr->firstObjPtr; \
- cachePtr->firstObjPtr = (objPtr)->internalRep.otherValuePtr; \
- --cachePtr->numObjects; \
- } \
- } while (0)
-
-# define TclFreeObjStorageEx(interp, objPtr) \
- do { \
- AllocCache *cachePtr; \
- if (((interp) == NULL) || \
- ((cachePtr = ((Interp *)(interp))->allocCache), \
- (cachePtr->numObjects >= ALLOC_NOBJHIGH))) { \
- TclThreadFreeObj(objPtr); \
- } else { \
- (objPtr)->internalRep.otherValuePtr = cachePtr->firstObjPtr; \
- cachePtr->firstObjPtr = objPtr; \
- ++cachePtr->numObjects; \
- } \
- } while (0)
-
-#else /* not PURIFY or USE_THREAD_ALLOC */
+#if defined(TCL_ALLOCATOR) && ((TCL_ALLOCATOR < 0) || (TCL_ALLOCATOR > aMULTI))
+#undef TCL_ALLOCATOR
+#endif
-#ifdef TCL_THREADS
-/* declared in tclObj.c */
-MODULE_SCOPE Tcl_Mutex tclObjMutex;
+#ifdef PURIFY
+# undef TCL_ALLOCATOR
+# define TCL_ALLOCATOR aPURIFY
#endif
-# define TclAllocObjStorageEx(interp, objPtr) \
- do { \
- Tcl_MutexLock(&tclObjMutex); \
- if (tclFreeObjList == NULL) { \
- TclAllocateFreeObjects(); \
- } \
- (objPtr) = tclFreeObjList; \
- tclFreeObjList = (Tcl_Obj *) \
- tclFreeObjList->internalRep.otherValuePtr; \
- Tcl_MutexUnlock(&tclObjMutex); \
- } while (0)
+#if !defined(TCL_ALLOCATOR)
+# if defined(USE_THREAD_ALLOC) || defined(USE_TCLALLOC)
+# define TCL_ALLOCATOR aZIPPY
+# else
+# define TCL_ALLOCATOR aNATIVE
+# endif
+#endif
-# define TclFreeObjStorageEx(interp, objPtr) \
- do { \
- Tcl_MutexLock(&tclObjMutex); \
- (objPtr)->internalRep.otherValuePtr = (void *) tclFreeObjList; \
- tclFreeObjList = (objPtr); \
- Tcl_MutexUnlock(&tclObjMutex); \
- } while (0)
+#if TCL_ALLOCATOR < aNONE /* native or purify */
+# define TclpAlloc(size) ckalloc(size)
+# define TclpRealloc(ptr, size) ckrealloc((ptr),(size))
+# define TclpFree(size) ckfree(size)
+#else
+ MODULE_SCOPE char * TclpAlloc(unsigned int size);
+ MODULE_SCOPE char * TclpRealloc(char * ptr, unsigned int size);
+ MODULE_SCOPE void TclpFree(char * ptr);
#endif
-#else /* TCL_MEM_DEBUG */
-MODULE_SCOPE void TclDbInitNewObj(Tcl_Obj *objPtr, const char *file,
- int line);
+#if TCL_ALLOCATOR == aPURIFY
+# define TclSmallAlloc() ckalloc(sizeof(Tcl_Obj))
+# define TclSmallFree(ptr) ckfree(ptr)
+# define TclInitAlloc()
+# define TclFinalizeAlloc()
+#else
+ MODULE_SCOPE void * TclSmallAlloc();
+ MODULE_SCOPE void TclSmallFree(void *ptr);
+ MODULE_SCOPE void TclInitAlloc(void);
+ MODULE_SCOPE void TclFinalizeAlloc(void);
+#endif
-# define TclDbNewObj(objPtr, file, line) \
- do { \
- TclIncrObjsAllocated(); \
- (objPtr) = (Tcl_Obj *) \
- Tcl_DbCkalloc(sizeof(Tcl_Obj), (file), (line)); \
- TclDbInitNewObj((objPtr), (file), (line)); \
- TCL_DTRACE_OBJ_CREATE(objPtr); \
+#define TclCkSmallAlloc(nbytes, memPtr) \
+ do { \
+ TCL_CT_ASSERT((nbytes)<=sizeof(Tcl_Obj)); \
+ memPtr = TclSmallAlloc(); \
} while (0)
-# define TclNewObj(objPtr) \
- TclDbNewObj(objPtr, __FILE__, __LINE__);
+/*
+ * Support for Clang Static Analyzer <http://clang-analyzer.llvm.org>
+ */
-# define TclDecrRefCount(objPtr) \
- Tcl_DbDecrRefCount(objPtr, __FILE__, __LINE__)
+#if (TCL_ALLOCATOR == aPURIFY) && defined(__clang__)
+#if __has_feature(attribute_analyzer_noreturn) && \
+ !defined(Tcl_Panic) && defined(Tcl_Panic_TCL_DECLARED)
+void Tcl_Panic(const char *, ...) __attribute__((analyzer_noreturn));
+#endif
+#if !defined(CLANG_ASSERT)
+#include <assert.h>
+#define CLANG_ASSERT(x) assert(x)
+#endif
+#elif !defined(CLANG_ASSERT)
+ #define CLANG_ASSERT(x)
+#endif /* PURIFY && __clang__ */
-# define TclNewListObjDirect(objc, objv) \
- TclDbNewListObjDirect(objc, objv, __FILE__, __LINE__)
-#undef USE_THREAD_ALLOC
-#endif /* TCL_MEM_DEBUG */
/*
*----------------------------------------------------------------
@@ -4471,73 +4409,11 @@ MODULE_SCOPE Tcl_PackageInitProc Procbodytest_SafeInit;
{enum { ct_assert_value = 1/(!!(e)) };}
/*
- *----------------------------------------------------------------
- * Allocator for small structs (<=sizeof(Tcl_Obj)) using the Tcl_Obj pool.
- * Only checked at compile time.
- *
- * ONLY USE FOR CONSTANT nBytes.
- *
- * DO NOT LET THEM CROSS THREAD BOUNDARIES
- *----------------------------------------------------------------
- */
-
-#define TclSmallAlloc(nbytes, memPtr) \
- TclSmallAllocEx(NULL, (nbytes), (memPtr))
-
-#define TclSmallFree(memPtr) \
- TclSmallFreeEx(NULL, (memPtr))
-
-#ifndef TCL_MEM_DEBUG
-#define TclSmallAllocEx(interp, nbytes, memPtr) \
- do { \
- Tcl_Obj *objPtr; \
- TCL_CT_ASSERT((nbytes)<=sizeof(Tcl_Obj)); \
- TclIncrObjsAllocated(); \
- TclAllocObjStorageEx((interp), (objPtr)); \
- memPtr = (ClientData) (objPtr); \
- } while (0)
-
-#define TclSmallFreeEx(interp, memPtr) \
- do { \
- TclFreeObjStorageEx((interp), (Tcl_Obj *) (memPtr)); \
- TclIncrObjsFreed(); \
- } while (0)
-
-#else /* TCL_MEM_DEBUG */
-#define TclSmallAllocEx(interp, nbytes, memPtr) \
- do { \
- Tcl_Obj *objPtr; \
- TCL_CT_ASSERT((nbytes)<=sizeof(Tcl_Obj)); \
- TclNewObj(objPtr); \
- memPtr = (ClientData) objPtr; \
- } while (0)
-
-#define TclSmallFreeEx(interp, memPtr) \
- do { \
- Tcl_Obj *objPtr = (Tcl_Obj *) memPtr; \
- objPtr->bytes = NULL; \
- objPtr->typePtr = NULL; \
- objPtr->refCount = 1; \
- TclDecrRefCount(objPtr); \
- } while (0)
-#endif /* TCL_MEM_DEBUG */
-
-/*
* Support for Clang Static Analyzer <http://clang-analyzer.llvm.org>
*/
-#if defined(PURIFY) && defined(__clang__)
-#if __has_feature(attribute_analyzer_noreturn) && \
- !defined(Tcl_Panic) && defined(Tcl_Panic_TCL_DECLARED)
-void Tcl_Panic(const char *, ...) __attribute__((analyzer_noreturn));
-#endif
-#if !defined(CLANG_ASSERT)
-#include <assert.h>
-#define CLANG_ASSERT(x) assert(x)
-#endif
-#elif !defined(CLANG_ASSERT)
#define CLANG_ASSERT(x)
-#endif /* PURIFY && __clang__ */
+
/*
*----------------------------------------------------------------
@@ -4610,8 +4486,8 @@ typedef struct NRE_callback {
#if NRE_USE_SMALL_ALLOC
#define TCLNR_ALLOC(interp, ptr) \
- TclSmallAllocEx(interp, sizeof(NRE_callback), (ptr))
-#define TCLNR_FREE(interp, ptr) TclSmallFreeEx((interp), (ptr))
+ TclCkSmallAlloc(sizeof(NRE_callback), (ptr))
+#define TCLNR_FREE(interp, ptr) TclSmallFree(ptr)
#else
#define TCLNR_ALLOC(interp, ptr) \
(ptr = ((ClientData) ckalloc(sizeof(NRE_callback))))