From 1e1ef494a55763339c8a182eb636b25dccd47411 Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Fri, 22 Apr 2011 11:14:30 +0200 Subject: [PATCH 1/6] adjust posix.mak to be usable under windows and build both debug and release versions to different targets --- posix.mak | 91 ++++++++++++++++++++++++++++++++++++++++--------------- win32.mak | 45 +++++++++++++++------------ 2 files changed, 91 insertions(+), 45 deletions(-) diff --git a/posix.mak b/posix.mak index 5e0d44e2bd..baed7ca8f0 100644 --- a/posix.mak +++ b/posix.mak @@ -22,19 +22,40 @@ endif DMD=dmd +MKDIR=mkdir + DOCDIR=doc IMPDIR=import MODEL=32 -DFLAGS=-m$(MODEL) -O -release -inline -nofloat -w -d -Isrc -Iimport -UDFLAGS=-m$(MODEL) -O -release -nofloat -w -d -Isrc -Iimport +ifeq ($(BUILD),debug) + OPTFLAGS=-g + CFLAGS += -g +else + OPTFLAGS=-O -release -inline +endif -CFLAGS=-m$(MODEL) -O +DFLAGS=-m$(MODEL) $(OPTFLAGS) -nofloat -w -d -Isrc -Iimport +UDFLAGS=-m$(MODEL) $(OPTFLAGS) -nofloat -w -d -Isrc -Iimport + +# Set CFLAGS +ifeq ($(CC),cc) + CFLAGS += -m$(MODEL) + ifneq ($(BUILD),debug) + CFLAGS += -O + endif +endif OBJDIR=obj +LIBDIR=lib +JSONDIR=. DRUNTIME_BASE=druntime -DRUNTIME=lib/lib$(DRUNTIME_BASE).a +ifeq (Windows_NT,$(OS)) + DRUNTIME=$(LIBDIR)/$(DRUNTIME_BASE).lib +else + DRUNTIME=$(LIBDIR)/lib$(DRUNTIME_BASE).a +endif DOCFMT= @@ -263,12 +284,6 @@ SRC_D_MODULES = \ core/stdc/time \ core/stdc/wchar_ \ \ - core/sys/posix/sys/select \ - core/sys/posix/sys/socket \ - core/sys/posix/sys/stat \ - core/sys/posix/sys/wait \ - core/sys/posix/netinet/in_ \ - \ core/sync/barrier \ core/sync/condition \ core/sync/config \ @@ -287,7 +302,6 @@ SRC_D_MODULES = \ rt/aApply \ rt/aApplyR \ rt/adi \ - rt/alloca \ rt/arrayassign \ rt/arraybyte \ rt/arraycast \ @@ -298,10 +312,7 @@ SRC_D_MODULES = \ rt/arrayreal \ rt/arrayshort \ rt/cast_ \ - rt/cmath2 \ rt/cover \ - rt/critical_ \ - rt/deh2 \ rt/dmain2 \ rt/invariant \ rt/invariant_ \ @@ -309,7 +320,6 @@ SRC_D_MODULES = \ rt/llmath \ rt/memory \ rt/memset \ - rt/monitor_ \ rt/obj \ rt/qsort \ rt/switch_ \ @@ -357,12 +367,43 @@ SRC_D_MODULES = \ rt/typeinfo/ti_void \ rt/typeinfo/ti_wchar +SRC_D_MODULES_POSIX = \ + core/sys/posix/sys/select \ + core/sys/posix/sys/socket \ + core/sys/posix/sys/stat \ + core/sys/posix/sys/wait \ + core/sys/posix/netinet/in_ \ + \ + rt/alloca \ + rt/cmath2 \ + rt/critical_ \ + rt/deh2 \ + rt/monitor_ \ + +SRC_D_MODULES_WIN = \ + core/sys/windows/_dll \ + core/sys/windows/_thread \ + core/sys/windows/dbghelp \ + core/sys/windows/stacktrace \ + core/sys/windows/windows \ + \ + rt/deh \ + # NOTE: trace.d and cover.d are not necessary for a successful build # as both are used for debugging features (profiling and coverage) # NOTE: a pre-compiled minit.obj has been provided in dmd for Win32 and # minit.asm is not used by dmd for Linux -OBJS= $(OBJDIR)/errno_c.o $(OBJDIR)/threadasm.o $(OBJDIR)/complex.o $(OBJDIR)/memory_osx.o +ifeq (Windows_NT,$(OS)) + SRC_D_MODULES += $(SRC_D_MODULES_WIN) + O = obj + OBJS= $(OBJDIR)/errno_c.obj $(OBJDIR)/monitor.obj $(OBJDIR)/complex.obj $(OBJDIR)/critical.obj \ + src\rt\minit.obj +else + SRC_D_MODULES += $(SRC_D_MODULES_POSIX) + O = o + OBJS= $(OBJDIR)/errno_c.o $(OBJDIR)/threadasm.o $(OBJDIR)/complex.o $(OBJDIR)/memory_osx.o +endif DOCS=\ $(DOCDIR)/object.html \ @@ -499,22 +540,22 @@ $(IMPDIR)/core/%.di : src/core/%.d ################### C/ASM Targets ############################ -$(OBJDIR)/%.o : src/rt/%.c - @mkdir -p $(OBJDIR) +$(OBJDIR)/%.$O : src/rt/%.c + @$(MKDIR) -p $(OBJDIR) $(CC) -c $(CFLAGS) $< -o$@ -$(OBJDIR)/errno_c.o : src/core/stdc/errno.c - @mkdir -p $(OBJDIR) +$(OBJDIR)/errno_c.$O : src/core/stdc/errno.c + @$(MKDIR) -p $(OBJDIR) $(CC) -c $(CFLAGS) $< -o$@ -$(OBJDIR)/threadasm.o : src/core/threadasm.S - @mkdir -p $(OBJDIR) +$(OBJDIR)/threadasm.$O : src/core/threadasm.S + @$(MKDIR) -p $(OBJDIR) $(CC) -c $(CFLAGS) $< -o$@ ################### Library generation ######################### -$(DRUNTIME): $(OBJS) $(SRCS) win32.mak - $(DMD) -lib -of$(DRUNTIME) -Xfdruntime.json $(DFLAGS) $(SRCS) $(OBJS) +$(DRUNTIME): $(OBJS) $(SRCS) posix.mak + $(DMD) -lib -of$(DRUNTIME) -Xf$(JSONDIR)\druntime.json $(DFLAGS) $(SRCS) $(OBJS) unittest : $(addprefix $(OBJDIR)/,$(SRC_D_MODULES)) $(DRUNTIME) $(OBJDIR)/emptymain.d @echo done @@ -539,7 +580,7 @@ $(OBJDIR)/% : src/%.d $(DRUNTIME) $(OBJDIR)/emptymain.d @touch $@ $(OBJDIR)/emptymain.d : - @mkdir -p $(OBJDIR) + @$(MKDIR) -p $(OBJDIR) @echo 'void main(){}' >$@ detab: diff --git a/win32.mak b/win32.mak index 854ba11c7b..add4d344aa 100644 --- a/win32.mak +++ b/win32.mak @@ -1,24 +1,25 @@ -DMD=dmd +DMD=..\dmd\src\dmd -CC=dmc +CC=c:\l\dmc\bin\dmc DOCDIR=doc IMPDIR=import +LIBDIR=..\lib\ +OBJDIR=..\obj\$(DRUNTIME_BASE)\ -DFLAGS=-O -release -inline -nofloat -w -d -Isrc -Iimport +DBGFLAGS=-g -O -release -inline +DFLAGS=$(DBGFLAGS) -nofloat -w -d -Isrc -Iimport UDFLAGS=-O -release -nofloat -w -d -Isrc -Iimport -CFLAGS= +CFLAGS=-g DRUNTIME_BASE=druntime -DRUNTIME=lib\$(DRUNTIME_BASE).lib -GCSTUB=lib\gcstub.obj +DRUNTIME=$(LIBDIR)$(DRUNTIME_BASE).lib +GCSTUB=$(LIBDIR)gcstub.obj DOCFMT= -target : import $(DRUNTIME) doc $(GCSTUB) - MANIFEST= \ LICENSE_1_0.txt \ README.txt \ @@ -339,10 +340,12 @@ SRCS= \ # NOTE: a pre-compiled minit.obj has been provided in dmd for Win32 and # minit.asm is not used by dmd for Linux -OBJS= errno_c.obj complex.obj src\rt\minit.obj monitor.obj critical.obj -OBJS_TO_DELETE= errno_c.obj complex.obj monitor.obj critical.obj +OBJS_TO_DELETE = $(OBJDIR)errno_c.obj $(OBJDIR)complex.obj $(OBJDIR)monitor.obj $(OBJDIR)critical.obj +OBJS = $(OBJS_TO_DELETE) src\rt\minit.obj + +DOCS = -DOCS=\ +xDOCS=\ $(DOCDIR)\object.html \ $(DOCDIR)\core_atomic.html \ $(DOCDIR)\core_bitop.html \ @@ -453,6 +456,8 @@ IMPORTS=\ $(IMPDIR)\core\sys\windows\stacktrace.di \ $(IMPDIR)\core\sys\windows\windows.di +target : $(DOCS) $(IMPORTS) $(DRUNTIME) $(GCSTUB) + ######################## Doc .html file generation ############################## doc: $(DOCS) @@ -757,20 +762,20 @@ $(IMPDIR)\core\sys\windows\windows.di : src\core\sys\windows\windows.d ################### C\ASM Targets ############################ -errno_c.obj : src\core\stdc\errno.c - $(CC) -c $(CFLAGS) src\core\stdc\errno.c -oerrno_c.obj +$(OBJDIR)errno_c.obj : src\core\stdc\errno.c + $(CC) -c $(CFLAGS) -o$@ src\core\stdc\errno.c -complex.obj : src\rt\complex.c - $(CC) -c $(CFLAGS) src\rt\complex.c +$(OBJDIR)complex.obj : src\rt\complex.c + $(CC) -c $(CFLAGS) -o$@ src\rt\complex.c src\rt\minit.obj : src\rt\minit.asm - $(CC) -c $(CFLAGS) src\rt\minit.asm + $(CC) -c $(CFLAGS) -o$@ src\rt\minit.asm -critical.obj : src\rt\critical.c - $(CC) -c $(CFLAGS) src\rt\critical.c +$(OBJDIR)critical.obj : src\rt\critical.c + $(CC) -c $(CFLAGS) -o$@ src\rt\critical.c -monitor.obj : src\rt\monitor.c - $(CC) -c $(CFLAGS) src\rt\monitor.c +$(OBJDIR)monitor.obj : src\rt\monitor.c + $(CC) -c $(CFLAGS) -o$@ src\rt\monitor.c ################### gcstub generation ######################### From 864bb10cab2e0a3807df27962a73990b9e44c1e1 Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Fri, 22 Apr 2011 18:39:45 +0200 Subject: [PATCH 2/6] add DLL support for Windows Server 2003 and XP/64 fix crash in DLL on Windows/64 support creating thread inside DLL --- src/core/sys/windows/_dll.d | 82 ++++++++++++++++++++++++++-------- src/core/sys/windows/_thread.d | 23 ++++++---- src/core/thread.d | 16 ++++++- 3 files changed, 92 insertions(+), 29 deletions(-) diff --git a/src/core/sys/windows/_dll.d b/src/core/sys/windows/_dll.d index 1d384dada1..0a4e199f34 100644 --- a/src/core/sys/windows/_dll.d +++ b/src/core/sys/windows/_dll.d @@ -52,8 +52,8 @@ private: alias extern(Windows) void* fnRtlAllocateHeap(void* HeapHandle, uint Flags, uint Size); - // find a code sequence and return the (relative) address that follows - static void* findCodeReference( void* adr, int len, ref ubyte[] pattern, bool relative ) + // find a code sequence and return the address after the sequence + static void* findCodeSequence( void* adr, int len, ref ubyte[] pattern ) { if( !adr ) return null; @@ -64,14 +64,28 @@ private: if( code[ p .. p + pattern.length ] == pattern[ 0 .. $ ] ) { ubyte* padr = code + p + pattern.length; - if( relative ) - return padr + 4 + *cast(int*) padr; - return *cast(void**) padr; + return padr; } } return null; } + // find a code sequence and return the (relative) address that follows + static void* findCodeReference( void* adr, int len, ref ubyte[] pattern, bool relative ) + { + if( !adr ) + return null; + + ubyte* padr = cast(ubyte*) findCodeSequence( adr, len, pattern ); + if( padr ) + { + if( relative ) + return padr + 4 + *cast(int*) padr; + return *cast(void**) padr; + } + return null; + } + // crawl through ntdll to find function _LdrpAllocateTls@0 and references // to _LdrpNumberOfTlsEntries, _NtdllBaseTag and _LdrpTlsList // LdrInitializeThunk @@ -87,11 +101,14 @@ private: static __gshared ubyte[] jmp_LdrpInitialize = [ 0x33, 0xED, 0xE9 ]; // xor ebp,ebp; jmp _LdrpInitialize static __gshared ubyte[] jmp__LdrpInitialize = [ 0x5D, 0xE9 ]; // pop ebp; jmp __LdrpInitialize + static __gshared ubyte[] jmp__LdrpInitialize_xp64 = [ 0x5D, 0x90, 0x90, 0x90, 0x90, 0x90 ]; // pop ebp; nop; nop; nop; nop; nop; static __gshared ubyte[] call_LdrpInitializeThread = [ 0xFF, 0x75, 0x08, 0xE8 ]; // push [ebp+8]; call _LdrpInitializeThread static __gshared ubyte[] call_LdrpAllocateTls = [ 0x00, 0x00, 0xE8 ]; // jne 0xc3; call _LdrpAllocateTls + static __gshared ubyte[] call_LdrpAllocateTls_svr03 = [ 0x65, 0xfc, 0x00, 0xE8 ]; // and [ebp+fc], 0; call _LdrpAllocateTls static __gshared ubyte[] jne_LdrpAllocateTls = [ 0x0f, 0x85 ]; // jne body_LdrpAllocateTls static __gshared ubyte[] mov_LdrpNumberOfTlsEntries = [ 0x8B, 0x0D ]; // mov ecx, _LdrpNumberOfTlsEntries static __gshared ubyte[] mov_NtdllBaseTag = [ 0x51, 0x8B, 0x0D ]; // push ecx; mov ecx, _NtdllBaseTag + static __gshared ubyte[] mov_NtdllBaseTag_srv03 = [ 0x50, 0xA1 ]; // push eax; mov eax, _NtdllBaseTag static __gshared ubyte[] mov_LdrpTlsList = [ 0x8B, 0x3D ]; // mov edi, _LdrpTlsList static LdrpTlsListEntry* addTlsListEntry( void** peb, void* tlsstart, void* tlsend, void* tls_callbacks_a, int* tlsindex ) @@ -105,13 +122,19 @@ private: { void* pLdrpInitialize = findCodeReference( fn, 20, jmp_LdrpInitialize, true ); void* p_LdrpInitialize = findCodeReference( pLdrpInitialize, 40, jmp__LdrpInitialize, true ); + if( !p_LdrpInitialize ) + p_LdrpInitialize = findCodeSequence( pLdrpInitialize, 40, jmp__LdrpInitialize_xp64 ); void* pLdrpInitializeThread = findCodeReference( p_LdrpInitialize, 200, call_LdrpInitializeThread, true ); void* pLdrpAllocateTls = findCodeReference( pLdrpInitializeThread, 40, call_LdrpAllocateTls, true ); + if(!pLdrpAllocateTls) + pLdrpAllocateTls = findCodeReference( pLdrpInitializeThread, 100, call_LdrpAllocateTls_svr03, true ); void* pBodyAllocateTls = findCodeReference( pLdrpAllocateTls, 40, jne_LdrpAllocateTls, true ); - int* pLdrpNumberOfTlsEntries = cast(int*) findCodeReference( pBodyAllocateTls, 20, mov_LdrpNumberOfTlsEntries, false ); + int* pLdrpNumberOfTlsEntries = cast(int*) findCodeReference( pBodyAllocateTls, 60, mov_LdrpNumberOfTlsEntries, false ); pNtdllBaseTag = cast(int*) findCodeReference( pBodyAllocateTls, 30, mov_NtdllBaseTag, false ); - LdrpTlsListEntry* pLdrpTlsList = cast(LdrpTlsListEntry*)findCodeReference( pBodyAllocateTls, 60, mov_LdrpTlsList, false ); + if(!pNtdllBaseTag) + pNtdllBaseTag = cast(int*) findCodeReference( pBodyAllocateTls, 30, mov_NtdllBaseTag_srv03, false ); + LdrpTlsListEntry* pLdrpTlsList = cast(LdrpTlsListEntry*)findCodeReference( pBodyAllocateTls, 80, mov_LdrpTlsList, false ); if( !pLdrpNumberOfTlsEntries || !pNtdllBaseTag || !pLdrpTlsList ) return null; @@ -346,8 +369,12 @@ public: function (uint id, void* context) { if( !thread_findByAddr( id ) ) { - thread_attachByAddr( id ); - thread_moduleTlsCtor( id ); + // if the OS has not prepared TLS for us, don't attach to the thread + if( GetTlsDataAddress( id ) ) + { + thread_attachByAddr( id ); + thread_moduleTlsCtor( id ); + } } return true; }, null ); @@ -382,22 +409,39 @@ public: */ static bool tlsCtorRun; static this() { tlsCtorRun = true; } + static ~this() { tlsCtorRun = false; } // to be called from DllMain with reason DLL_THREAD_ATTACH - void dll_thread_attach( bool attach_thread = true, bool initTls = true ) + bool dll_thread_attach( bool attach_thread = true, bool initTls = true ) { - if( attach_thread && !thread_findByAddr( GetCurrentThreadId() ) ) - thread_attachThis(); - if( initTls && !tlsCtorRun ) // avoid duplicate calls - _moduleTlsCtor(); + // if the OS has not prepared TLS for us, don't attach to the thread + // (happened when running under x64 OS) + if( !GetTlsDataAddress( GetCurrentThreadId() ) ) + return false; + if( !thread_findByAddr( GetCurrentThreadId() ) ) + { + // only attach to thread and initalize it if it is not in the thread list (so it's not created by "new Thread") + if( attach_thread ) + thread_attachThis(); + if( initTls && !tlsCtorRun ) // avoid duplicate calls + _moduleTlsCtor(); + } + return true; } // to be called from DllMain with reason DLL_THREAD_DETACH - void dll_thread_detach( bool detach_thread = true, bool exitTls = true ) + bool dll_thread_detach( bool detach_thread = true, bool exitTls = true ) { - if( exitTls ) - _moduleTlsDtor(); - if( detach_thread ) - thread_detachThis(); + // if the OS has not prepared TLS for us, we did not attach to the thread + if( !GetTlsDataAddress( GetCurrentThreadId() ) ) + return false; + if( thread_findByAddr( GetCurrentThreadId() ) ) + { + if( exitTls && tlsCtorRun ) // avoid dtors to be run twice + _moduleTlsDtor(); + if( detach_thread ) + thread_detachThis(); + } + return true; } } diff --git a/src/core/sys/windows/_thread.d b/src/core/sys/windows/_thread.d index 6fcac8cf9c..8df9e601e3 100644 --- a/src/core/sys/windows/_thread.d +++ b/src/core/sys/windows/_thread.d @@ -201,7 +201,7 @@ private: return; } - // temporarily set current TLS data pointer to the data pointer of the referenced thread + // temporarily set current TLS array pointer to the array pointer of the referenced thread void** curteb = getTEB(); void** teb = getTEB( id ); assert( teb && curteb ); @@ -211,14 +211,9 @@ private: if( !curtlsarray || !tlsarray ) return; - void** curtlsdata = cast(void**) curtlsarray[_tls_index]; - void** tlsdata = cast(void**) tlsarray[_tls_index]; - if( !curtlsdata || !tlsdata ) - return; - - curtlsarray[_tls_index] = tlsdata; + curteb[11] = tlsarray; fn(); - curtlsarray[_tls_index] = curtlsdata; + curteb[11] = curtlsarray; } } @@ -229,6 +224,7 @@ public: alias thread_aux.OpenThreadHandle OpenThreadHandle; alias thread_aux.enumProcessThreads enumProcessThreads; + // get the start of the TLS memory of the thread with the given handle void* GetTlsDataAddress( HANDLE hnd ) { if( void** teb = getTEB( hnd ) ) @@ -237,6 +233,17 @@ public: return null; } + // get the start of the TLS memory of the thread with the given identifier + void* GetTlsDataAddress( uint id ) + { + HANDLE hnd = OpenThread( thread_aux.THREAD_QUERY_INFORMATION, FALSE, id ); + assert( hnd, "OpenThread failed" ); + + void* tls = GetTlsDataAddress( hnd ); + CloseHandle( hnd ); + return tls; + } + /////////////////////////////////////////////////////////////////// // run _moduleTlsCtor in the context of the given thread void thread_moduleTlsCtor( uint id ) diff --git a/src/core/thread.d b/src/core/thread.d index 5d160099da..a3a6adad03 100644 --- a/src/core/thread.d +++ b/src/core/thread.d @@ -794,6 +794,16 @@ class Thread // having thread being treated like a daemon thread. synchronized( slock ) { + // when creating threads from inside a DLL, DllMain(THREAD_ATTACH) + // might be called before _beginthreadex returns, but the dll + // helper functions need to know whether the thread is created + // from the runtime itself or from another DLL or the application + // to just attach to it + // as the consequence, the new Thread object is added before actual + // creation of the thread. There should be no problem with the GC + // calling thread_suspendAll, because of the slock synchronization + add( this ); + version( Windows ) { m_hndl = cast(HANDLE) _beginthreadex( null, m_sz, &thread_entryPoint, cast(void*) this, 0, &m_addr ); @@ -817,7 +827,6 @@ class Thread if( m_tmach == m_tmach.init ) throw new ThreadException( "Error creating thread" ); } - add( this ); } } @@ -2039,7 +2048,10 @@ version( Windows ) auto pstart = cast(void*) &_tlsstart; auto pend = cast(void*) &_tlsend; auto pos = GetTlsDataAddress( thisThread.m_hndl ); - thisThread.m_tls = pos[0 .. pend - pstart]; + if( pos ) // on x64, threads without TLS happen to exist + thisThread.m_tls = pos[0 .. pend - pstart]; + else + thisThread.m_tls = []; } } else From 7987fb97bd1c9285888d09c1779392a67c6522cc Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Fri, 22 Apr 2011 18:41:56 +0200 Subject: [PATCH 3/6] fix some issues when building and using a debug version of druntime --- src/gc/gcx.d | 2 ++ src/rt/arraycat.d | 4 ++-- src/rt/deh.d | 6 ++++-- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/gc/gcx.d b/src/gc/gcx.d index 35803ccad1..d095db19c1 100644 --- a/src/gc/gcx.d +++ b/src/gc/gcx.d @@ -25,6 +25,7 @@ module gc.gcx; //debug = SENTINEL; // add underrun/overrrun protection //debug = PTRCHECK; // more pointer checking //debug = PTRCHECK2; // thorough but slow pointer checking +//debug = GCXINVARIANT; // more invariants (seem not thread safe) /*************** Configuration *********************/ @@ -1549,6 +1550,7 @@ struct Gcx void Invariant() { } + debug(GCXINVARIANT) invariant() { if (inited) diff --git a/src/rt/arraycat.d b/src/rt/arraycat.d index c0aaa4df0a..61e2614b15 100644 --- a/src/rt/arraycat.d +++ b/src/rt/arraycat.d @@ -23,8 +23,8 @@ extern (C): byte[] _d_arraycopy(size_t size, byte[] from, byte[] to) { - debug printf("f = %p,%d, t = %p,%d, size = %d\n", - from.ptr, from.length, to.ptr, to.length, size); + debug(PRINTF) printf("f = %p,%d, t = %p,%d, size = %d\n", + from.ptr, from.length, to.ptr, to.length, size); if (to.length != from.length) { diff --git a/src/rt/deh.d b/src/rt/deh.d index e3d918ab94..f3f7ea584f 100644 --- a/src/rt/deh.d +++ b/src/rt/deh.d @@ -424,12 +424,13 @@ EXCEPTION_DISPOSITION _d_framehandler( ClassInfo masterClassInfo; // Class info of the Master exception. masterClassInfo = null; // only compute it if we need it + DHandlerInfo *phinfo = &handlerTable.handler_info[0]; // avoid bounds check // walk through handler table, checking each handler // with an index smaller than the current table_index for (ndx = frame.table_index; ndx != -1; ndx = prev_ndx) { - phi = &handlerTable.handler_info[ndx]; + phi = phinfo + ndx; prev_ndx = phi.prev_index; if (phi.cioffset) { @@ -794,9 +795,10 @@ void _d_local_unwind(DHandlerTable *handler_table, push dword ptr FS:_except_list; mov FS:_except_list,ESP; } + DHandlerInfo *phinfo = &handler_table.handler_info[0]; // avoid bounds check for (i = frame.table_index; i != -1 && i != stop_index; i = phi.prev_index) { - phi = &handler_table.handler_info[i]; + phi = phinfo + i; if (phi.finally_code) { // Note that it is unnecessary to adjust the ESP, as the finally block From 4e84b5303c5b79a36a27ab772f145f63a9cdf3db Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Mon, 25 Apr 2011 15:28:56 +0200 Subject: [PATCH 4/6] add windows unittest support to posix.mak add _d_monitorenter_d_monitorexit to object.di, they are needed to build the (empty) unittest for deh.d --- import/object.di | 3 +++ posix.mak | 9 +++++++++ 2 files changed, 12 insertions(+) diff --git a/import/object.di b/import/object.di index 30b858a2ad..505efb6401 100644 --- a/import/object.di +++ b/import/object.di @@ -355,6 +355,9 @@ extern (C) void* _d_assocarrayliteralT(TypeInfo_AssociativeArray ti, size_t length, ...); } +extern (C) void _d_monitorenter(Object h); +extern (C) void _d_monitorexit(Object h); + struct AssociativeArray(Key, Value) { void* p; diff --git a/posix.mak b/posix.mak index baed7ca8f0..e5e39b96de 100644 --- a/posix.mak +++ b/posix.mak @@ -571,6 +571,10 @@ $(addprefix $(OBJDIR)/,$(DISABLED_TESTS)) : $(OBJDIR)/% : src/%.d $(DRUNTIME) $(OBJDIR)/emptymain.d @echo Testing $@ +ifeq (Windows_NT,$(OS)) + @$(DMD) $(UDFLAGS) -unittest $(subst /,\,-of$@ -map $@.map $(OBJDIR)/emptymain.d) $< -debuglib=$(DRUNTIME_BASE) -defaultlib=$(DRUNTIME_BASE) + @$(RUN) $@ +else @$(DMD) $(UDFLAGS) -unittest -of$@ $(OBJDIR)/emptymain.d $< -L-Llib -debuglib=$(DRUNTIME_BASE) -defaultlib=$(DRUNTIME_BASE) # make the file very old so it builds and runs again if it fails @touch -t 197001230123 $@ @@ -578,10 +582,15 @@ $(OBJDIR)/% : src/%.d $(DRUNTIME) $(OBJDIR)/emptymain.d @$(RUN) $@ # succeeded, render the file new again @touch $@ +endif $(OBJDIR)/emptymain.d : @$(MKDIR) -p $(OBJDIR) +ifeq (Windows_NT,$(OS)) + @echo void main(){} >$@ +else @echo 'void main(){}' >$@ +endif detab: detab $(MANIFEST) From b4f4842e2566af4165ca13db0645dab8488948b5 Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Mon, 25 Apr 2011 15:30:10 +0200 Subject: [PATCH 5/6] add demangle function that allows skipping the return type information --- src/core/demangle.d | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/core/demangle.d b/src/core/demangle.d index 6d3763336e..cba8e5d951 100644 --- a/src/core/demangle.d +++ b/src/core/demangle.d @@ -1342,6 +1342,11 @@ char[] demangle( const(char)[] buf, char[] dst = null ) return d(); } +char[] demangle( const(char)[] buf, bool addType_, char[] dst = null ) +{ + auto d = Demangle(buf, addType_ ? Demangle.AddType.yes : Demangle.AddType.no, dst); + return d(); +} unittest { From 0bb4bc6b87185c1516269dbaec02a233d022b7bc Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Mon, 25 Apr 2011 15:31:32 +0200 Subject: [PATCH 6/6] fix gcx invariant: calling divisor initializer detected invalid intermediate state --- src/gc/gcx.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gc/gcx.d b/src/gc/gcx.d index d095db19c1..d26d8a44f9 100644 --- a/src/gc/gcx.d +++ b/src/gc/gcx.d @@ -3055,6 +3055,7 @@ struct Pool { this.isLargeObject = isLargeObject; size_t poolsize; + auto div = this.divisor; //debug(PRINTF) printf("Pool::Pool(%u)\n", npages); poolsize = npages * PAGESIZE; @@ -3074,7 +3075,6 @@ struct Pool } //assert(baseAddr); topAddr = baseAddr + poolsize; - auto div = this.divisor; auto nbits = cast(size_t)poolsize / div; mark.alloc(nbits);