From 2fdfefd2fc6b15e7ad044ff8f1c58216827847b3 Mon Sep 17 00:00:00 2001 From: Andy Wingo Date: Wed, 23 Feb 2022 21:25:26 +0100 Subject: [PATCH] handlify --- GCBench.c | 186 +++++++++++++++++++++++++++--------------------------- bdw.h | 52 +++++++++++++++ 2 files changed, 146 insertions(+), 92 deletions(-) diff --git a/GCBench.c b/GCBench.c index 5a0f2015f..8331e82be 100644 --- a/GCBench.c +++ b/GCBench.c @@ -42,6 +42,12 @@ #include #include +typedef struct Node { + struct Node * left; + struct Node * right; + int i, j; +} Node; + #ifdef GC_BDW #include "bdw.h" #else @@ -65,17 +71,9 @@ static const int kArraySize = 500000; // about 4Mb static const int kMinTreeDepth = 4; static const int kMaxTreeDepth = 16; -typedef struct Node0_struct { - struct Node0_struct * left; - struct Node0_struct * right; - int i, j; -} Node0; - -typedef Node0 *Node; - -void init_Node(Node me, Node l, Node r) { - me -> left = l; - me -> right = r; +void init_Node(Node *me, Node *l, Node *r) { + init_field((void**)&me->left, l); + init_field((void**)&me->right, r); } // Nodes used by a tree of a given size @@ -89,132 +87,136 @@ static int NumIters(int i) { } // Build tree top down, assigning to older objects. -static void Populate(int iDepth, Node thisNode) { +static void Populate(int iDepth, Node *node) { if (iDepth<=0) { return; } else { iDepth--; - thisNode->left = GC_NEW(Node0); - thisNode->right = GC_NEW(Node0); - Populate (iDepth, thisNode->left); - Populate (iDepth, thisNode->right); + + NodeHandle self = { node }; + PUSH_HANDLE(self); + NodeHandle l = { allocate_node() }; + PUSH_HANDLE(l); + NodeHandle r = { allocate_node() }; + PUSH_HANDLE(r); + set_field((void**)&HANDLE_REF(self)->left, HANDLE_REF(l)); + set_field((void**)&HANDLE_REF(self)->right, HANDLE_REF(r)); + Populate (iDepth, HANDLE_REF(self)->left); + Populate (iDepth, HANDLE_REF(self)->right); + POP_HANDLE(r); + POP_HANDLE(l); + POP_HANDLE(self); } } // Build tree bottom-up -static Node MakeTree(int iDepth) { - Node result; +static Node* MakeTree(int iDepth) { if (iDepth<=0) { - result = GC_NEW(Node0); - /* result is implicitly initialized in both cases. */ - return result; + return allocate_node(); } else { - Node left = MakeTree(iDepth-1); - Node right = MakeTree(iDepth-1); - result = GC_NEW(Node0); - init_Node(result, left, right); + NodeHandle left = { MakeTree(iDepth-1) }; + PUSH_HANDLE(left); + NodeHandle right = { MakeTree(iDepth-1) }; + PUSH_HANDLE(right); + Node *result = allocate_node(); + init_Node(result, HANDLE_REF(left), HANDLE_REF(right)); + POP_HANDLE(left); + POP_HANDLE(right); return result; } } -static void PrintDiagnostics() { -#if 0 - long lFreeMemory = Runtime.getRuntime().freeMemory(); - long lTotalMemory = Runtime.getRuntime().totalMemory(); - - System.out.print(" Total memory available=" - + lTotalMemory + " bytes"); - System.out.println(" Free memory=" + lFreeMemory + " bytes"); -#endif -} - static void TimeConstruction(int depth) { - long tStart, tFinish; - int iNumIters = NumIters(depth); - Node tempTree; - int i; + int iNumIters = NumIters(depth); + NodeHandle tempTree = { NULL }; + PUSH_HANDLE(tempTree); printf("Creating %d trees of depth %d\n", iNumIters, depth); - - tStart = currentTime(); - for (i = 0; i < iNumIters; ++i) { - tempTree = GC_NEW(Node0); - Populate(depth, tempTree); - tempTree = 0; - } - tFinish = currentTime(); - printf("\tTop down construction took %d msec\n", - tFinish - tStart); - - tStart = currentTime(); - for (i = 0; i < iNumIters; ++i) { - tempTree = MakeTree(depth); - tempTree = 0; - } - tFinish = currentTime(); - printf("\tBottom up construction took %d msec\n", - tFinish - tStart); + { + long tStart = currentTime(); + for (int i = 0; i < iNumIters; ++i) { + HANDLE_SET(tempTree, allocate_node()); + Populate(depth, HANDLE_REF(tempTree)); + HANDLE_SET(tempTree, NULL); + } + long tFinish = currentTime(); + printf("\tTop down construction took %ld msec\n", + tFinish - tStart); + } + + { + long tStart = currentTime(); + for (int i = 0; i < iNumIters; ++i) { + HANDLE_SET(tempTree, MakeTree(depth)); + HANDLE_SET(tempTree, NULL); + } + long tFinish = currentTime(); + printf("\tBottom up construction took %ld msec\n", + tFinish - tStart); + } + + POP_HANDLE(tempTree); } int main() { - Node root; - Node longLivedTree; - Node tempTree; - long tStart, tFinish; - long tElapsed; - int i, d; - double *array; + NodeHandle root = { NULL }; + NodeHandle longLivedTree = { NULL }; + NodeHandle tempTree = { NULL }; + HANDLE_TO(double) array = { NULL }; + + PUSH_HANDLE(root); + PUSH_HANDLE(longLivedTree); + PUSH_HANDLE(tempTree); + PUSH_HANDLE(array); + + initialize_gc(); - // GC_full_freq = 30; - // GC_free_space_divisor = 16; - // GC_enable_incremental(); printf("Garbage Collector Test\n"); - printf(" Live storage will peak at %d bytes.\n\n", - 2 * sizeof(Node0) * TreeSize(kLongLivedTreeDepth) + + printf(" Live storage will peak at %zd bytes.\n\n", + 2 * sizeof(struct Node) * TreeSize(kLongLivedTreeDepth) + sizeof(double) * kArraySize); printf(" Stretching memory with a binary tree of depth %d\n", kStretchTreeDepth); - PrintDiagnostics(); -# ifdef PROFIL - init_profiling(); -# endif + print_start_gc_stats(); - tStart = currentTime(); + long tStart = currentTime(); // Stretch the memory space quickly - tempTree = MakeTree(kStretchTreeDepth); - tempTree = 0; + HANDLE_SET(tempTree, MakeTree(kStretchTreeDepth)); + HANDLE_SET(tempTree, NULL); // Create a long lived object printf(" Creating a long-lived binary tree of depth %d\n", kLongLivedTreeDepth); - longLivedTree = GC_NEW(Node0); - Populate(kLongLivedTreeDepth, longLivedTree); + HANDLE_SET(longLivedTree, allocate_node()); + Populate(kLongLivedTreeDepth, HANDLE_REF(longLivedTree)); // Create long-lived array, filling half of it printf(" Creating a long-lived array of %d doubles\n", kArraySize); - array = GC_MALLOC_ATOMIC(sizeof(double) * kArraySize); - for (i = 0; i < kArraySize/2; ++i) { - array[i] = 1.0/i; + HANDLE_SET(array, allocate_double_array(kArraySize)); + for (int i = 0; i < kArraySize/2; ++i) { + HANDLE_REF(array)[i] = 1.0/i; } - PrintDiagnostics(); - for (d = kMinTreeDepth; d <= kMaxTreeDepth; d += 2) { + for (int d = kMinTreeDepth; d <= kMaxTreeDepth; d += 2) { TimeConstruction(d); } - if (longLivedTree == 0 || array[1000] != 1.0/1000) + if (HANDLE_REF(longLivedTree) == 0 || HANDLE_REF(array)[1000] != 1.0/1000) fprintf(stderr, "Failed\n"); // fake reference to LongLivedTree // and array // to keep them from being optimized away - tFinish = currentTime(); - tElapsed = tFinish - tStart; - PrintDiagnostics(); - printf("Completed in %d msec\n", tElapsed); - printf("Completed %d collections\n", GC_gc_no); - printf("Heap size is %d\n", GC_get_heap_size()); + long tFinish = currentTime(); + long tElapsed = tFinish - tStart; + printf("Completed in %ld msec\n", tElapsed); + print_end_gc_stats(); + + POP_HANDLE(array); + POP_HANDLE(tempTree); + POP_HANDLE(longLivedTree); + POP_HANDLE(root); } diff --git a/bdw.h b/bdw.h index 28932aea8..aea294ac6 100644 --- a/bdw.h +++ b/bdw.h @@ -11,3 +11,55 @@ #define GC_NO_THREAD_REDIRECTS 1 #include + +static Node* allocate_node(void) { + // memset to 0 by the collector. + return GC_malloc (sizeof (Node)); +} + +static double* allocate_double_array(size_t size) { + // note, not memset to 0 by the collector. + return GC_malloc_atomic (sizeof (double) * size); +} + +struct handle { + void *v; +}; + +#define HANDLE_TO(T) union { T* v; struct handle handle; } +#define HANDLE_REF(h) h.v +#define HANDLE_SET(h,val) do { h.v = val; } while (0) +#define PUSH_HANDLE(h) push_handle(&h.handle) +#define POP_HANDLE(h) pop_handle(&h.handle) + +typedef HANDLE_TO(Node) NodeHandle; + +static inline void push_handle(struct handle *handle) { +} + +static inline void pop_handle(struct handle *handle) { +} + +static inline void init_field(void **addr, void *val) { + *addr = val; +} +static inline void set_field(void **addr, void *val) { + *addr = val; +} +static inline void* get_field(void **addr) { + return *addr; +} + +static inline void initialize_gc(void) { + // GC_full_freq = 30; + // GC_free_space_divisor = 16; + // GC_enable_incremental(); +} + +static inline void print_start_gc_stats(void) { +} + +static inline void print_end_gc_stats(void) { + printf("Completed %ld collections\n", (long)GC_get_gc_no()); + printf("Heap size is %ld\n", (long)GC_get_heap_size()); +}