diff --git a/src/backend/executor/execGrouping.c b/src/backend/executor/execGrouping.c
index 47c9656..2d9ce93 100644
--- a/src/backend/executor/execGrouping.c
+++ b/src/backend/executor/execGrouping.c
@@ -330,7 +330,8 @@ BuildTupleHashTable(int numCols, AttrNumber *keyColIdx,
 	else
 		hashtable->hash_iv = 0;
 
-	hashtable->hashtab = tuplehash_create(tablecxt, nbuckets);
+	hashtable->hashtab =
+			tuplehash_create(tablecxt, nbuckets, NULL, NULL, NULL);
 	hashtable->hashtab->private_data = hashtable;
 
 	return hashtable;
diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index 7b31948..36102b5 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -244,7 +244,7 @@ tbm_create_pagetable(TIDBitmap *tbm)
 	Assert(tbm->status != TBM_HASH);
 	Assert(tbm->pagetable == NULL);
 
-	tbm->pagetable = pagetable_create(tbm->mcxt, 128);
+	tbm->pagetable = pagetable_create(tbm->mcxt, 128, NULL, NULL, NULL);
 
 	/* If entry1 is valid, push it into the hashtable */
 	if (tbm->status == TBM_ONE_PAGE)
diff --git a/src/include/lib/simplehash.h b/src/include/lib/simplehash.h
index 12aedbc..8c3e726 100644
--- a/src/include/lib/simplehash.h
+++ b/src/include/lib/simplehash.h
@@ -90,6 +90,12 @@
 /* generate forward declarations necessary to use the hash table */
 #ifdef SH_DECLARE
 
+/* Allocation function for hash table elements */
+typedef void *(*element_allocate) (Size size, void *args);
+
+/* Free function */
+typedef void (*element_free) (void *pointer, void *args);
+
 /* type definitions */
 typedef struct SH_TYPE
 {
@@ -112,8 +118,17 @@ typedef struct SH_TYPE
 	/* hash buckets */
 	SH_ELEMENT_TYPE *data;
 
+	/* Allocation function for hash table elements */
+	element_allocate alloc;
+
+	/* Free function */
+	element_free free;
+
+	/* Arguments to be passed to allocation and free functions */
+	void	   *args;
+
 	/* memory context to use for allocations */
-	MemoryContext ctx;
+	MemoryContext element_allocator_ctx;
 
 	/* user defined data, useful for callbacks */
 	void	   *private_data;
@@ -133,7 +148,8 @@ typedef struct SH_ITERATOR
 } SH_ITERATOR;
 
 /* externally visible function prototypes */
-SH_SCOPE SH_TYPE *SH_CREATE(MemoryContext ctx, uint32 nelements);
+SH_SCOPE SH_TYPE *SH_CREATE(MemoryContext ctx, uint32 nelements,
+		  element_allocate alloc, element_free free, void *args);
 SH_SCOPE void SH_DESTROY(SH_TYPE *tb);
 SH_SCOPE void SH_GROW(SH_TYPE *tb, uint32 newsize);
 SH_SCOPE SH_ELEMENT_TYPE *SH_INSERT(SH_TYPE *tb, SH_KEY_TYPE key, bool *found);
@@ -276,27 +292,62 @@ SH_ENTRY_HASH(SH_TYPE *tb, SH_ELEMENT_TYPE * entry)
 #endif
 }
 
+/* default memory allocator function */
+static void *
+SH_DEFAULT_ALLOC(Size size, void *args)
+{
+	MemoryContext context = (MemoryContext) args;
+
+	return MemoryContextAllocExtended(context, size,
+									  MCXT_ALLOC_HUGE | MCXT_ALLOC_ZERO);
+}
+
+/* default memory free function */
+static void
+SH_DEFAULT_FREE(void *pointer, void *args)
+{
+	pfree(pointer);
+}
+
 /*
  * Create a hash table with enough space for `nelements` distinct members,
  * allocating required memory in the passed-in context.
+ *
+ * WARNING : alloc is an allocator handle which provides memory allocator
+ * function for storing hash elements. User needs to be aware that providing
+ * allocator does not store complete hash table in the allocator memory i.e
+ * hash table will still be allocated in local memory. However all the
+ * elements will be stored in the memory provided by the allocator.
  */
 SH_SCOPE SH_TYPE *
-SH_CREATE(MemoryContext ctx, uint32 nelements)
+SH_CREATE(MemoryContext ctx, uint32 nelements, element_allocate alloc,
+		  element_free free, void *args)
 {
-	SH_TYPE    *tb;
-	uint64		size;
+	SH_TYPE     *tb;
+	uint64		 size;
 
 	tb = MemoryContextAllocZero(ctx, sizeof(SH_TYPE));
-	tb->ctx = ctx;
+	tb->element_allocator_ctx = ctx;
 
 	/* increase nelements by fillfactor, want to store nelements elements */
 	size = Min((double) SH_MAX_SIZE, ((double) nelements) / SH_FILLFACTOR);
 
 	SH_COMPUTE_PARAMETERS(tb, size);
 
-	tb->data = MemoryContextAllocExtended(tb->ctx,
-										  sizeof(SH_ELEMENT_TYPE) * tb->size,
-										  MCXT_ALLOC_HUGE | MCXT_ALLOC_ZERO);
+	if (!alloc)
+	{
+		tb->alloc = (element_allocate) SH_DEFAULT_ALLOC;
+		tb->free = (element_free) SH_DEFAULT_FREE;
+		tb->args = (void *) ctx;
+	}
+	else
+	{
+		tb->alloc = alloc;
+		tb->free = free;
+		tb->args = args;
+	}
+
+	tb->data = tb->alloc(sizeof(SH_ELEMENT_TYPE) * tb->size, tb->args);
 
 	return tb;
 }
@@ -305,7 +356,7 @@ SH_CREATE(MemoryContext ctx, uint32 nelements)
 SH_SCOPE void
 SH_DESTROY(SH_TYPE *tb)
 {
-	pfree(tb->data);
+	tb->free(tb->data, tb->args);
 	pfree(tb);
 }
 
@@ -333,9 +384,7 @@ SH_GROW(SH_TYPE *tb, uint32 newsize)
 	/* compute parameters for new table */
 	SH_COMPUTE_PARAMETERS(tb, newsize);
 
-	tb->data = MemoryContextAllocExtended(
-								 tb->ctx, sizeof(SH_ELEMENT_TYPE) * tb->size,
-										  MCXT_ALLOC_HUGE | MCXT_ALLOC_ZERO);
+	tb->data = tb->alloc(sizeof(SH_ELEMENT_TYPE) * tb->size, tb->args);
 
 	newdata = tb->data;
 
@@ -421,7 +470,7 @@ SH_GROW(SH_TYPE *tb, uint32 newsize)
 		}
 	}
 
-	pfree(olddata);
+	tb->free(olddata, tb->args);
 }
 
 /*
