diff -uNr dmd-0.111/dmd/src/phobos/internal/gc/gc.d dmd-0.112/dmd/src/phobos/internal/gc/gc.d --- dmd-0.111/dmd/src/phobos/internal/gc/gc.d 2005-01-19 12:14:24.000000000 +0100 +++ dmd-0.112/dmd/src/phobos/internal/gc/gc.d 2005-01-27 01:05:38.000000000 +0100 @@ -33,9 +33,16 @@ import gcx; import std.outofmemory; import gcstats; -//import std.math; +import std.thread; -GC* _gc; +version=GCCLASS; + +version (GCCLASS) + alias GC gc_t; +else + alias GC* gc_t; + +gc_t _gc; void addRoot(void *p) { _gc.addRoot(p); } void removeRoot(void *p) { _gc.removeRoot(p); } @@ -49,6 +56,29 @@ void enable() { _gc.enable(); } void getStats(out GCStats stats) { _gc.getStats(stats); } +void* getGCHandle() +{ + return cast(void*)_gc; +} + +void setGCHandle(void* p) +{ + void* oldp = getGCHandle(); + gc_t g = cast(gc_t)p; + if (g.gcversion != gcx.GCVERSION) + throw new Error("incompatible gc versions"); + + // Add our static data to the new gc + GC.scanStaticData(g); + + _gc = g; +// return oldp; +} + +void endGCHandle() +{ + GC.unscanStaticData(_gc); +} extern (C) { @@ -58,10 +88,21 @@ void gc_init() { - _gc = cast(GC *) std.c.stdlib.calloc(1, GC.sizeof); + version (GCCLASS) + { void* p; + ClassInfo ci = GC.classinfo; + + p = std.c.stdlib.malloc(ci.init.length); + (cast(byte*)p)[0 .. ci.init.length] = ci.init[]; + _gc = cast(GC)p; + } + else + { + _gc = cast(GC *) std.c.stdlib.calloc(1, GC.sizeof); + } _gc.initialize(); - //_gc.setStackBottom(_atopsp); - _gc.scanStaticData(); + GC.scanStaticData(_gc); + std.thread.Thread.thread_init(); } void gc_term() diff -uNr dmd-0.111/dmd/src/phobos/internal/gc/gcstub.d dmd-0.112/dmd/src/phobos/internal/gc/gcstub.d --- dmd-0.111/dmd/src/phobos/internal/gc/gcstub.d 1970-01-01 01:00:00.000000000 +0100 +++ dmd-0.112/dmd/src/phobos/internal/gc/gcstub.d 2005-01-27 01:05:38.000000000 +0100 @@ -0,0 +1,212 @@ +/* + * Copyright (C) 2004 by Digital Mars, www.digitalmars.com + * Written by Walter Bright + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * o The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * o Altered source versions must be plainly marked as such, and must not + * be misrepresented as being the original software. + * o This notice may not be removed or altered from any source + * distribution. + */ + +// D Garbage Collector stub to prevent linking in gc + +module gcx; + +//debug=PRINTF; + +/***************************************************/ + + +version (Win32) +{ + import win32; +} + +version (linux) +{ + import gclinux; +} + + +//alias GC* gc_t; +alias GC gc_t; + +struct GCStats { } + +/* ============================ GC =============================== */ + + +//alias int size_t; +alias void (*GC_FINALIZER)(void *p, void *dummy); + +const uint GCVERSION = 1; // increment every time we change interface + // to GC. + +class GC +{ + uint gcversion = GCVERSION; + + void *gcx; // implementation + + void initialize() + { + debug(PRINTF) printf("initialize()\n"); + } + + + void Dtor() + { + debug(PRINTF) printf("Dtor()\n"); + } + + invariant + { + debug(PRINTF) printf("invariant()\n"); + } + + void *malloc(size_t size) + { + debug(PRINTF) printf("malloc()\n"); + return null; + } + + void *mallocNoSync(size_t size) + { + debug(PRINTF) printf("mallocNoSync()\n"); + return null; + } + + + void *calloc(size_t size, size_t n) + { + debug(PRINTF) printf("calloc()\n"); + return null; + } + + + void *realloc(void *p, size_t size) + { + debug(PRINTF) printf("realloc()\n"); + return null; + } + + + void free(void *p) + { + debug(PRINTF) printf("free()\n"); + } + + size_t capacity(void *p) + { + debug(PRINTF) printf("capacity()\n"); + return 0; + } + + void check(void *p) + { + debug(PRINTF) printf("check()\n"); + } + + + void setStackBottom(void *p) + { + debug(PRINTF) printf("setStackBottom()\n"); + } + + static void scanStaticData(gc_t g) + { + void *pbot; + void *ptop; + uint nbytes; + + debug(PRINTF) printf("scanStaticData()\n"); + //debug(PRINTF) printf("+GC.scanStaticData()\n"); + os_query_staticdataseg(&pbot, &nbytes); + ptop = pbot + nbytes; + g.addRange(pbot, ptop); + //debug(PRINTF) printf("-GC.scanStaticData()\n"); + } + + static void unscanStaticData(gc_t g) + { + void *pbot; + uint nbytes; + + debug(PRINTF) printf("unscanStaticData()\n"); + os_query_staticdataseg(&pbot, &nbytes); + g.removeRange(pbot); + } + + + void addRoot(void *p) // add p to list of roots + { + debug(PRINTF) printf("addRoot()\n"); + } + + void removeRoot(void *p) // remove p from list of roots + { + debug(PRINTF) printf("removeRoot()\n"); + } + + void addRange(void *pbot, void *ptop) // add range to scan for roots + { + debug(PRINTF) printf("addRange()\n"); + } + + void removeRange(void *pbot) // remove range + { + debug(PRINTF) printf("removeRange()\n"); + } + + void fullCollect() // do full garbage collection + { + debug(PRINTF) printf("fullCollect()\n"); + } + + void fullCollectNoStack() // do full garbage collection + { + debug(PRINTF) printf("fullCollectNoStack()\n"); + } + + void genCollect() // do generational garbage collection + { + debug(PRINTF) printf("genCollect()\n"); + } + + void minimize() // minimize physical memory usage + { + debug(PRINTF) printf("minimize()\n"); + } + + void setFinalizer(void *p, GC_FINALIZER pFn) + { + debug(PRINTF) printf("setFinalizer()\n"); + } + + void enable() + { + debug(PRINTF) printf("enable()\n"); + } + + void disable() + { + debug(PRINTF) printf("disable()\n"); + } + + void getStats(out GCStats stats) + { + debug(PRINTF) printf("getStats()\n"); + } +} diff -uNr dmd-0.111/dmd/src/phobos/internal/gc/gcx.d dmd-0.112/dmd/src/phobos/internal/gc/gcx.d --- dmd-0.111/dmd/src/phobos/internal/gc/gcx.d 2005-01-19 12:14:24.000000000 +0100 +++ dmd-0.112/dmd/src/phobos/internal/gc/gcx.d 2005-01-27 01:05:38.000000000 +0100 @@ -52,6 +52,9 @@ import std.thread; } +//alias GC* gc_t; +alias GC gc_t; + /* ======================= Leak Detector =========================== */ debug (LOGGING) @@ -155,13 +158,18 @@ class GCLock { } // just a dummy so we can get a global lock -struct GC +const uint GCVERSION = 1; // increment every time we change interface + // to GC. + +class GC { // For passing to debug code static uint line; static char *file; - Gcx *gcx; // implementation + uint gcversion = GCVERSION; + + Gcx *gcx; // implementation static ClassInfo gcLock; // global lock void initialize() @@ -526,7 +534,7 @@ } } - void scanStaticData() + static void scanStaticData(gc_t g) { void *pbot; void *ptop; @@ -535,10 +543,19 @@ //debug(PRINTF) printf("+GC.scanStaticData()\n"); os_query_staticdataseg(&pbot, &nbytes); ptop = pbot + nbytes; - addRange(pbot, ptop); + g.addRange(pbot, ptop); //debug(PRINTF) printf("-GC.scanStaticData()\n"); } + static void unscanStaticData(gc_t g) + { + void *pbot; + uint nbytes; + + os_query_staticdataseg(&pbot, &nbytes); + g.removeRange(pbot); + } + void addRoot(void *p) // add p to list of roots { diff -uNr dmd-0.111/dmd/src/phobos/internal/gc/testgc.d dmd-0.112/dmd/src/phobos/internal/gc/testgc.d --- dmd-0.111/dmd/src/phobos/internal/gc/testgc.d 2005-01-19 12:14:24.000000000 +0100 +++ dmd-0.112/dmd/src/phobos/internal/gc/testgc.d 2005-01-27 01:05:38.000000000 +0100 @@ -15,7 +15,32 @@ import gcx; import std.random; -void printStats(GC *gc) +alias GC gc_t; +//alias GC* gc_t; + +gc_t newGC() +{ + version (all) + { void* p; + ClassInfo ci = GC.classinfo; + + p = std.c.stdlib.malloc(ci.init.length); + (cast(byte*)p)[0 .. ci.init.length] = ci.init[]; + return cast(GC)p; + } + else + { + return cast(gc_t)std.c.stdlib.calloc(1, GC.sizeof); + } +} + +void deleteGC(gc_t gc) +{ + gc.Dtor(); + std.c.stdlib.free(cast(void*)gc); +} + +void printStats(gc_t gc) { GCStats stats; @@ -62,7 +87,7 @@ void smoke() { - GC *gc; + gc_t gc; printf("--------------------------smoke()\n"); @@ -102,7 +127,7 @@ void smoke2() { - GC *gc; + gc_t gc; int *p; int i; @@ -147,7 +172,7 @@ void smoke3() { - GC *gc; + gc_t gc; int *p; int i; @@ -180,7 +205,7 @@ void smoke4() { - GC *gc; + gc_t gc; int *p; int i; @@ -211,7 +236,7 @@ /* ---------------------------- */ -void smoke5(GC *gc) +void smoke5(gc_t gc) { byte *p; int i; @@ -278,7 +303,7 @@ { test1(); - GC *gc; + gc_t gc; printf("GC test start\n"); @@ -298,14 +323,3 @@ printf("GC test success\n"); return EXIT_SUCCESS; } - -GC *newGC() -{ - return cast(GC *)std.c.stdlib.calloc(1, GC.sizeof); -} - -void deleteGC(GC *gc) -{ - gc.Dtor(); - std.c.stdlib.free(gc); -} diff -uNr dmd-0.111/dmd/src/phobos/internal/trace.d dmd-0.112/dmd/src/phobos/internal/trace.d --- dmd-0.111/dmd/src/phobos/internal/trace.d 1970-01-01 01:00:00.000000000 +0100 +++ dmd-0.112/dmd/src/phobos/internal/trace.d 2005-01-27 01:05:36.000000000 +0100 @@ -0,0 +1,859 @@ + +/* Trace dynamic profiler. + * For use with the Digital Mars DMD compiler. + * Copyright (C) 1995-2005 by Digital Mars + * All Rights Reserved + * Written by Walter Bright + * www.digitalmars.com + */ + +module internal.trace; + +import std.stdio; +import std.ctype; +import std.string; +import std.c.stdlib; + +extern (C): + +char* unmangle_ident(char*); // from DMC++ runtime library + +alias long timer_t; + +///////////////////////////////////// +// + +struct SymPair +{ + SymPair* next; + Symbol* sym; // function that is called + uint count; // number of times sym is called +} + +///////////////////////////////////// +// A Symbol for each function name. + +struct Symbol +{ + Symbol* Sl, Sr; // left, right children + SymPair* Sfanin; // list of calling functions + SymPair* Sfanout; // list of called functions + timer_t totaltime; // aggregate time + timer_t functime; // time excluding subfunction calls + ubyte Sflags; + char[] Sident; // name of symbol +} + +const ubyte SFvisited = 1; // visited + +static Symbol* root; // root of symbol table + +////////////////////////////////// +// Build a linked list of these. + +struct Stack +{ + Stack* prev; + Symbol* sym; + timer_t starttime; // time when function was entered + timer_t ohd; // overhead of all the bookkeeping code + timer_t subtime; // time used by all subfunctions +} + +static Stack* stack_freelist; +static Stack* trace_tos; // top of stack +static int trace_inited; // !=0 if initialized +static timer_t trace_ohd; + +static Symbol** psymbols; +static uint nsymbols; // number of symbols + +static char[] trace_logfilename = "trace.log"; +static FILE* fplog; + +static char[] trace_deffilename = "trace.def"; +static FILE* fpdef; + + +//////////////////////////////////////// +// Set file name for output. +// A file name of "" means write results to stdout. +// Returns: +// 0 success +// !=0 failure + +int trace_setlogfilename(char[] name) +{ + trace_logfilename = name; + return 0; +} + +//////////////////////////////////////// +// Set file name for output. +// A file name of "" means write results to stdout. +// Returns: +// 0 success +// !=0 failure + +int trace_setdeffilename(char[] name) +{ + trace_deffilename = name; + return 0; +} + +//////////////////////////////////////// +// Output optimal function link order. + +static void trace_order(Symbol *s) +{ + while (s) + { + trace_place(s,0); + if (s.Sl) + trace_order(s.Sl); + s = s.Sr; + } +} + +////////////////////////////////////////////// +// + +static Stack* stack_malloc() +{ Stack *s; + + if (stack_freelist) + { s = stack_freelist; + stack_freelist = s.prev; + } + else + s = cast(Stack *)trace_malloc(Stack.sizeof); + return s; +} + +////////////////////////////////////////////// +// + +static void stack_free(Stack *s) +{ + s.prev = stack_freelist; + stack_freelist = s; +} + +////////////////////////////////////// +// Qsort() comparison routine for array of pointers to SymPair's. + +static int sympair_cmp(void* e1, void* e2) +{ SymPair** psp1; + SymPair** psp2; + + psp1 = cast(SymPair**)e1; + psp2 = cast(SymPair**)e2; + + return (*psp2).count - (*psp1).count; +} + +////////////////////////////////////// +// Place symbol s, and then place any fan ins or fan outs with +// counts greater than count. + +static void trace_place(Symbol *s, uint count) +{ SymPair* sp; + SymPair** base; + + if (!(s.Sflags & SFvisited)) + { size_t num; + uint u; + + //printf("\t%.*s\t%u\n", s.Sident, count); + fprintf(fpdef,"\t%.*s\n", s.Sident); + s.Sflags |= SFvisited; + + // Compute number of items in array + num = 0; + for (sp = s.Sfanin; sp; sp = sp.next) + num++; + for (sp = s.Sfanout; sp; sp = sp.next) + num++; + if (!num) + return; + + // Allocate and fill array + base = cast(SymPair**)trace_malloc(SymPair.sizeof * num); + u = 0; + for (sp = s.Sfanin; sp; sp = sp.next) + base[u++] = sp; + for (sp = s.Sfanout; sp; sp = sp.next) + base[u++] = sp; + + // Sort array + qsort(base, num, (SymPair *).sizeof, &sympair_cmp); + + //for (u = 0; u < num; u++) + //printf("\t\t%.*s\t%u\n", base[u].sym.Sident, base[u].count); + + // Place symbols + for (u = 0; u < num; u++) + { + if (base[u].count >= count) + { uint u2; + uint c2; + + u2 = (u + 1 < num) ? u + 1 : u; + c2 = base[u2].count; + if (c2 < count) + c2 = count; + trace_place(base[u].sym,c2); + } + else + break; + } + + // Clean up + trace_free(base); + } +} + +///////////////////////////////////// +// Initialize and terminate. + +static this() +{ + trace_init(); +} + +static ~this() +{ + trace_term(); +} + +/////////////////////////////////// +// Report results. +// Also compute nsymbols. + +static void trace_report(Symbol* s) +{ SymPair* sp; + uint count; + + //printf("trace_report()\n"); + while (s) + { nsymbols++; + if (s.Sl) + trace_report(s.Sl); + fprintf(fplog,"------------------\n"); + count = 0; + for (sp = s.Sfanin; sp; sp = sp.next) + { + fprintf(fplog,"\t%5d\t%.*s\n", sp.count, sp.sym.Sident); + count += sp.count; + } + fprintf(fplog,"%.*s\t%u\t%lld\t%lld\n",s.Sident,count,s.totaltime,s.functime); + for (sp = s.Sfanout; sp; sp = sp.next) + { + fprintf(fplog,"\t%5d\t%.*s\n",sp.count,sp.sym.Sident); + } + s = s.Sr; + } +} + +//////////////////////////////////// +// Allocate and fill array of symbols. + +static void trace_array(Symbol *s) +{ static uint u; + + if (!psymbols) + { u = 0; + psymbols = cast(Symbol **)trace_malloc((Symbol *).sizeof * nsymbols); + } + while (s) + { + psymbols[u++] = s; + trace_array(s.Sl); + s = s.Sr; + } +} + + +////////////////////////////////////// +// Qsort() comparison routine for array of pointers to Symbol's. + +static int symbol_cmp(void* e1, void* e2) +{ Symbol** ps1; + Symbol** ps2; + timer_t diff; + + ps1 = cast(Symbol **)e1; + ps2 = cast(Symbol **)e2; + + diff = (*ps2).functime - (*ps1).functime; + return (diff == 0) ? 0 : ((diff > 0) ? 1 : -1); +} + + +/////////////////////////////////// +// Report function timings + +static void trace_times(Symbol* root) +{ uint u; + timer_t freq; + + // Sort array + qsort(psymbols, nsymbols, (Symbol *).sizeof, &symbol_cmp); + + // Print array + QueryPerformanceFrequency(&freq); + fprintf(fplog,"\n======== Timer Is %lld Ticks/Sec, Times are in Microsecs ========\n\n",freq); + fprintf(fplog," Num Tree Func Per\n"); + fprintf(fplog," Calls Time Time Call\n\n"); + for (u = 0; u < nsymbols; u++) + { Symbol* s = psymbols[u]; + timer_t tl,tr; + timer_t fl,fr; + timer_t pl,pr; + timer_t percall; + SymPair* sp; + uint calls; + char[] id; + + version (Win32) + { char* p = toStringz(s.Sident); + p = unmangle_ident(p); + if (p) + id = p[0 .. strlen(p)]; + } + if (!id) + id = s.Sident; + calls = 0; + for (sp = s.Sfanin; sp; sp = sp.next) + calls += sp.count; + if (calls == 0) + calls = 1; + +version (all) +{ + tl = (s.totaltime * 1000000) / freq; + fl = (s.functime * 1000000) / freq; + percall = s.functime / calls; + pl = (s.functime * 1000000) / calls / freq; + + fprintf(fplog,"%7d%12lld%12lld%12lld %.*s\n", + calls,tl,fl,pl,id); +} +else +{ + tl = s.totaltime / freq; + tr = ((s.totaltime - tl * freq) * 10000000) / freq; + + fl = s.functime / freq; + fr = ((s.functime - fl * freq) * 10000000) / freq; + + percall = s.functime / calls; + pl = percall / freq; + pr = ((percall - pl * freq) * 10000000) / freq; + + fprintf(fplog,"%7d\t%3lld.%07lld\t%3lld.%07lld\t%3lld.%07lld\t%.*s\n", + calls,tl,tr,fl,fr,pl,pr,id); +} + if (id !== s.Sident) + free(id); + } +} + + +/////////////////////////////////// +// Initialize. + +static void trace_init() +{ + if (!trace_inited) + { + trace_inited = 1; + + { // See if we can determine the overhead. + uint u; + timer_t starttime; + timer_t endtime; + Stack *st; + + st = trace_tos; + trace_tos = null; + QueryPerformanceCounter(&starttime); + for (u = 0; u < 100; u++) + { + asm + { + call _trace_pro_n ; + db 0 ; + call _trace_epi_n ; + } + } + QueryPerformanceCounter(&endtime); + trace_ohd = (endtime - starttime) / u; + //printf("trace_ohd = %lld\n",trace_ohd); + if (trace_ohd > 0) + trace_ohd--; // round down + trace_tos = st; + } + } +} + +///////////////////////////////// +// Terminate. + +void trace_term() +{ + //printf("trace_term()\n"); + if (trace_inited == 1) + { Stack *n; + + trace_inited = 2; + + // Free remainder of the stack + while (trace_tos) + { + n = trace_tos.prev; + stack_free(trace_tos); + trace_tos = n; + } + + while (stack_freelist) + { + n = stack_freelist.prev; + stack_free(stack_freelist); + stack_freelist = n; + } + + // Merge in data from any existing file + trace_merge(); + + // Report results + fplog = fopen(trace_logfilename,"w"); + //fplog = std.c.stdio.stdout; + if (fplog) + { nsymbols = 0; + trace_report(root); + trace_array(root); + trace_times(root); + fclose(fplog); + } + + // Output function link order + fpdef = fopen(trace_deffilename,"w"); + if (fpdef) + { fprintf(fpdef,"\nFUNCTIONS\n"); + trace_order(root); + fclose(fpdef); + } + + trace_free(psymbols); + psymbols = null; + } +} + +///////////////////////////////// +// Our storage allocator. + +static void *trace_malloc(size_t nbytes) +{ void *p; + + p = malloc(nbytes); + if (!p) + exit(EXIT_FAILURE); + return p; +} + +static void trace_free(void *p) +{ + free(p); +} + +////////////////////////////////////////////// +// + +static Symbol* trace_addsym(char[] id) +{ + Symbol** parent; + Symbol* rover; + Symbol* s; + int cmp; + char c; + + //printf("trace_addsym('%s',%d)\n",p,len); + parent = &root; + rover = *parent; + while (rover != null) // while we haven't run out of tree + { + cmp = std.string.cmp(id, rover.Sident); + if (cmp == 0) + { + return rover; + } + parent = (cmp < 0) ? /* if we go down left side */ + &(rover.Sl) : /* then get left child */ + &(rover.Sr); /* else get right child */ + rover = *parent; /* get child */ + } + /* not in table, so insert into table */ + s = cast(Symbol *)trace_malloc(Symbol.sizeof); + memset(s,0,Symbol.sizeof); + s.Sident = id; + *parent = s; // link new symbol into tree + return s; +} + +/*********************************** + * Add symbol s with count to SymPair list. + */ + +static void trace_sympair_add(SymPair** psp, Symbol* s, uint count) +{ SymPair* sp; + + for (; 1; psp = &sp.next) + { + sp = *psp; + if (!sp) + { + sp = cast(SymPair *)trace_malloc(SymPair.sizeof); + sp.sym = s; + sp.count = 0; + sp.next = null; + *psp = sp; + break; + } + else if (sp.sym == s) + { + break; + } + } + sp.count += count; +} + +////////////////////////////////////////////// +// + +static void trace_pro(char[] id) +{ + Stack* n; + Symbol* s; + timer_t starttime; + timer_t t; + + QueryPerformanceCounter(&starttime); + if (id.length == 0) + return; + if (!trace_inited) + trace_init(); // initialize package + n = stack_malloc(); + n.prev = trace_tos; + trace_tos = n; + s = trace_addsym(id); + trace_tos.sym = s; + if (trace_tos.prev) + { + Symbol* prev; + int i; + + // Accumulate Sfanout and Sfanin + prev = trace_tos.prev.sym; + trace_sympair_add(&prev.Sfanout,s,1); + trace_sympair_add(&s.Sfanin,prev,1); + } + QueryPerformanceCounter(&t); + trace_tos.starttime = starttime; + trace_tos.ohd = trace_ohd + t - starttime; + trace_tos.subtime = 0; + //printf("trace_tos.ohd=%lld, trace_ohd=%lld + t=%lld - starttime=%lld\n", + // trace_tos.ohd,trace_ohd,t,starttime); +} + +///////////////////////////////////////// +// + +static void trace_epi() +{ Stack* n; + timer_t endtime; + timer_t t; + timer_t ohd; + + //printf("trace_epi()\n"); + if (trace_tos) + { + timer_t starttime; + timer_t totaltime; + + QueryPerformanceCounter(&endtime); + starttime = trace_tos.starttime; + totaltime = endtime - starttime - trace_tos.ohd; + if (totaltime < 0) + { //printf("endtime=%lld - starttime=%lld - trace_tos.ohd=%lld < 0\n", + // endtime,starttime,trace_tos.ohd); + totaltime = 0; // round off error, just make it 0 + } + + // totaltime is time spent in this function + all time spent in + // subfunctions - bookkeeping overhead. + trace_tos.sym.totaltime += totaltime; + + //if (totaltime < trace_tos.subtime) + //printf("totaltime=%lld < trace_tos.subtime=%lld\n",totaltime,trace_tos.subtime); + trace_tos.sym.functime += totaltime - trace_tos.subtime; + ohd = trace_tos.ohd; + n = trace_tos.prev; + stack_free(trace_tos); + trace_tos = n; + if (n) + { QueryPerformanceCounter(&t); + n.ohd += ohd + t - endtime; + n.subtime += totaltime; + //printf("n.ohd = %lld\n",n.ohd); + } + } +} + + +////////////////////////// FILE INTERFACE ///////////////////////// + +///////////////////////////////////// +// Read line from file fp. +// Returns: +// trace_malloc'd line buffer +// null if end of file + +static char* trace_readline(FILE* fp) +{ int c; + int dim; + int i; + char *buf; + + //printf("trace_readline(%p)\n", fp); + i = 0; + dim = 0; + buf = null; + while (1) + { + if (i == dim) + { char *p; + + dim += 80; + p = cast(char *)trace_malloc(dim); + memcpy(p,buf,i); + trace_free(buf); + buf = p; + } + c = fgetc(fp); + switch (c) + { + case EOF: + if (i == 0) + { trace_free(buf); + return null; + } + case '\n': + goto L1; + default: + break; + } + buf[i] = c; + i++; + } +L1: + buf[i] = 0; + //printf("line '%s'\n",buf); + return buf; +} + +////////////////////////////////////// +// Skip space + +static char *skipspace(char *p) +{ + while (std.ctype.isspace(*p)) + p++; + return p; +} + +//////////////////////////////////////////////////////// +// Merge in profiling data from existing file. + +static void trace_merge() +{ FILE *fp; + char *buf; + char *p; + uint count; + Symbol *s; + SymPair *sfanin; + SymPair **psp; + + if (trace_logfilename && (fp = fopen(trace_logfilename,"r")) != null) + { + buf = null; + sfanin = null; + psp = &sfanin; + while (1) + { + trace_free(buf); + buf = trace_readline(fp); + if (!buf) + break; + switch (*buf) + { + case '=': // ignore rest of file + trace_free(buf); + goto L1; + case ' ': + case '\t': // fan in or fan out line + count = strtoul(buf,&p,10); + if (p == buf) // if invalid conversion + continue; + p = skipspace(p); + if (!*p) + continue; + s = trace_addsym(p[0 .. strlen(p)]); + trace_sympair_add(psp,s,count); + break; + default: + if (!isalpha(*buf)) + { + if (!sfanin) + psp = &sfanin; + continue; // regard unrecognized line as separator + } + case '?': + case '_': + case '$': + case '@': + p = buf; + while (std.ctype.isgraph(*p)) + p++; + *p = 0; + //printf("trace_addsym('%s')\n",buf); + s = trace_addsym(buf[0 .. strlen(buf)]); + if (s.Sfanin) + { SymPair *sp; + + for (; sfanin; sfanin = sp) + { + trace_sympair_add(&s.Sfanin,sfanin.sym,sfanin.count); + sp = sfanin.next; + trace_free(sfanin); + } + } + else + { s.Sfanin = sfanin; + } + sfanin = null; + psp = &s.Sfanout; + + { timer_t t; + + p++; + count = strtoul(p,&p,10); + t = strtoull(p,&p,10); + s.totaltime += t; + t = strtoull(p,&p,10); + s.functime += t; + } + break; + } + } + L1: + fclose(fp); + } +} + +////////////////////////// COMPILER INTERFACE ///////////////////// + +///////////////////////////////////////////// +// Function called by trace code in function prolog. + +void _trace_pro_n() +{ + /* Length of string is either: + * db length + * ascii string + * or: + * db 0x0FF + * db 0 + * dw length + * ascii string + */ + + asm + { naked ; + pushad ; + mov ECX,8*4[ESP] ; + xor EAX,EAX ; + mov AL,[ECX] ; + cmp AL,0xFF ; + jne L1 ; + cmp byte ptr 1[ECX],0 ; + jne L1 ; + mov AX,2[ECX] ; + add 8*4[ESP],3 ; + add ECX,3 ; + L1: inc EAX ; + inc ECX ; + add 8*4[ESP],EAX ; + dec EAX ; + push ECX ; + push EAX ; + call trace_pro ; + add ESP,8 ; + popad ; + ret ; + } +} + +///////////////////////////////////////////// +// Function called by trace code in function epilog. + + +void _trace_epi_n() +{ + asm + { naked ; + pushad ; + } + trace_epi(); + asm + { + popad ; + ret ; + } +} + + +version (Win32) +{ + extern (Windows) + { + export int QueryPerformanceCounter(timer_t *); + export int QueryPerformanceFrequency(timer_t *); + } +} +else version (X86) +{ + extern (D) + { + void QueryPerformanceCounter(timer_t* ctr) + { + asm + { naked ; + mov ECX,EAX ; + rdtsc ; + mov [ECX],EAX ; + mov 4[ECX],EDX ; + ret ; + } + } + + void QueryPerformanceFrequency(timer_t* freq) + { + *freq = 3579545; + } + } +} +else +{ + static assert(0); +} diff -uNr dmd-0.111/dmd/src/phobos/linux.mak dmd-0.112/dmd/src/phobos/linux.mak --- dmd-0.111/dmd/src/phobos/linux.mak 2005-01-19 12:14:22.000000000 +0100 +++ dmd-0.112/dmd/src/phobos/linux.mak 2005-01-27 01:05:32.000000000 +0100 @@ -56,7 +56,7 @@ crc32.o conv.o arraycast.o errno.o alloca.o cmath2.o \ process.o syserror.o \ socket.o socketstream.o stdarg.o stdio.o format.o \ - perf.o openrj.o uni.o \ + perf.o openrj.o uni.o trace.o \ ti_wchar.o ti_uint.o ti_short.o ti_ushort.o \ ti_byte.o ti_ubyte.o ti_long.o ti_ulong.o ti_ptr.o \ ti_float.o ti_double.o ti_real.o ti_delegate.o \ @@ -128,7 +128,7 @@ internal/memset.d internal/arraycast.d internal/aaA.d internal/adi.d \ internal/dmain2.d internal/cast.d internal/qsort.d internal/deh2.d \ internal/cmath2.d internal/obj.d internal/mars.h internal/aApply.d \ - internal/object.d + internal/object.d internal/trace.d SRC_STD_WIN= std/windows/registry.d \ std/windows/iunknown.d @@ -176,6 +176,7 @@ SRC_GC= internal/gc/gc.d \ internal/gc/gcx.d \ + internal/gc/gcstub.d \ internal/gc/gcbits.d \ internal/gc/win32.d \ internal/gc/gclinux.d \ @@ -447,6 +448,9 @@ switch.o : internal/switch.d $(DMD) -c $(DFLAGS) internal/switch.d +trace.o : internal/trace.d + $(DMD) -c $(DFLAGS) internal/trace.d + ### std array.o : std/array.d diff -uNr dmd-0.111/dmd/src/phobos/std/c/stdio.d dmd-0.112/dmd/src/phobos/std/c/stdio.d --- dmd-0.111/dmd/src/phobos/std/c/stdio.d 2005-01-19 12:14:22.000000000 +0100 +++ dmd-0.112/dmd/src/phobos/std/c/stdio.d 2005-01-27 01:05:34.000000000 +0100 @@ -97,6 +97,7 @@ version (Win32) { FILE _iob[_NFILE]; + void function() _fcloseallp; } version (Win32) diff -uNr dmd-0.111/dmd/src/phobos/std/gc.d dmd-0.112/dmd/src/phobos/std/gc.d --- dmd-0.111/dmd/src/phobos/std/gc.d 2005-01-19 12:14:22.000000000 +0100 +++ dmd-0.112/dmd/src/phobos/std/gc.d 2005-01-27 01:05:32.000000000 +0100 @@ -41,3 +41,23 @@ void enable(); void getStats(out GCStats stats); + +/*************************************** + * Get handle to the collector. + */ + +void* getGCHandle(); + +/*************************************** + * Set handle to the collector. + */ + +void setGCHandle(void* p); + +void endGCHandle(); + +extern (C) +{ + void gc_init(); + void gc_term(); +} diff -uNr dmd-0.111/dmd/src/phobos/std/thread.d dmd-0.112/dmd/src/phobos/std/thread.d --- dmd-0.111/dmd/src/phobos/std/thread.d 2005-01-19 12:14:22.000000000 +0100 +++ dmd-0.112/dmd/src/phobos/std/thread.d 2005-01-27 01:05:32.000000000 +0100 @@ -312,7 +312,7 @@ * Create a Thread for global main(). */ - static this() + static void thread_init() { threadLock = new Object(); @@ -323,19 +323,19 @@ t.hdl = Thread.getCurrentThreadHandle(); t.stackBottom = os_query_stackBottom(); - synchronized (threadLock) - { - assert(!allThreads[0]); - allThreads[0] = t; - allThreadsDim = 1; - t.idx = 0; - } + assert(!allThreads[0]); + allThreads[0] = t; + allThreadsDim = 1; + t.idx = 0; } static ~this() { - CloseHandle(allThreads[0].hdl); - allThreads[0].hdl = GetCurrentThread(); + if (allThreadsDim) + { + CloseHandle(allThreads[0].hdl); + allThreads[0].hdl = GetCurrentThread(); + } } /******************************************** @@ -768,7 +768,7 @@ * Create a Thread for global main(). */ - static this() + static void thread_init() { threadLock = new Object(); @@ -777,13 +777,11 @@ t.state = TS.RUNNING; t.id = pthread_self(); t.stackBottom = cast(void*)__libc_stack_end; - synchronized (threadLock) - { - assert(!allThreads[0]); - allThreads[0] = t; - allThreadsDim = 1; - t.idx = 0; - } + + assert(!allThreads[0]); + allThreads[0] = t; + allThreadsDim = 1; + t.idx = 0; /* Install signal handlers so we can suspend/resume threads */ diff -uNr dmd-0.111/dmd/src/phobos/win32.mak dmd-0.112/dmd/src/phobos/win32.mak --- dmd-0.111/dmd/src/phobos/win32.mak 2005-01-19 12:14:22.000000000 +0100 +++ dmd-0.112/dmd/src/phobos/win32.mak 2005-01-27 01:05:32.000000000 +0100 @@ -36,7 +36,7 @@ .asm.obj: $(CC) -c $* -targets : unittest +targets : unittest gcstub.obj unittest : unittest.exe unittest @@ -119,7 +119,7 @@ internal\memset.d internal\arraycast.d internal\aaA.d internal\adi.d \ internal\dmain2.d internal\cast.d internal\qsort.d internal\deh2.d \ internal\cmath2.d internal\obj.d internal\mars.h internal\aApply.d \ - internal\object.d + internal\object.d internal\trace.d SRC_STD_WIN= std\windows\registry.d \ std\windows\iunknown.d @@ -167,6 +167,7 @@ SRC_GC= internal\gc\gc.d \ internal\gc\gcx.d \ + internal\gc\gcstub.d \ internal\gc\gcbits.d \ internal\gc\win32.d \ internal\gc\gclinux.d \ @@ -385,6 +386,9 @@ dmain2.obj : internal\dmain2.d $(DMD) -c $(DFLAGS) internal\dmain2.d +gcstub.obj : internal\gc\gcstub.d + $(DMD) -c $(DFLAGS) -Iinternal\gc internal\gc\gcstub.d + invariant.obj : internal\invariant.d $(DMD) -c $(DFLAGS) internal\invariant.d @@ -699,7 +703,7 @@ del $(OBJS) install: - $(CP) phobos.lib \dmd\lib + $(CP) phobos.lib gcstub.obj \dmd\lib $(CP) win32.mak linux.mak minit.obj \dmd\src\phobos $(CP) $(SRC) \dmd\src\phobos $(CP) $(SRC_STD) \dmd\src\phobos\std