diff --git a/src/compilation.h b/src/compilation.h
index 15d62542526319a85a8cf20514e765449114bd55..8582d8fa246504534f8c2faccc4a836ccd4b508c 100644
--- a/src/compilation.h
+++ b/src/compilation.h
@@ -175,6 +175,7 @@
   IMEMBER(int, compat_minor, PIKE_MINOR_VERSION)
   ZMEMBER(int, flags, 0)
   ZMEMBER(struct compilation *,compiler,0)
+  ZMEMBER(struct block_allocator, node_allocator, BA_INIT_PAGES(sizeof(struct node_s), 2))
   SEND
 
 #undef PCODE
diff --git a/src/las.c b/src/las.c
index fe88ef323319a6056cffe3b9ba865a2c5677c12b..4d3b1b1737981b8346df5d9192c00634f5099c58 100644
--- a/src/las.c
+++ b/src/las.c
@@ -30,7 +30,7 @@
 #include "pikecode.h"
 #include "gc.h"
 #include "pike_compiler.h"
-#include "block_alloc.h"
+#include "block_allocator.h"
 
 /* Define this if you want the optimizer to be paranoid about aliasing
  * effects to to indexing.
@@ -455,75 +455,91 @@ static int check_node_type(node *n, struct pike_type *t, const char *msg)
   return 1;
 }
 
-#undef BLOCK_ALLOC_NEXT
-#define BLOCK_ALLOC_NEXT u.node.a
+void init_node_s_blocks() { }
 
-#undef PRE_INIT_BLOCK
-#define PRE_INIT_BLOCK(NODE) do {					\
-    (NODE)->token = USHRT_MAX;						\
-  } while (0)
+void really_free_node_s(node * n) {
+    ba_free(&Pike_compiler->node_allocator, n);
+}
 
-BLOCK_ALLOC_FILL_PAGES(node_s, 2)
+MALLOC_FUNCTION
+node * alloc_node_s() {
+    return (node*)ba_alloc(&Pike_compiler->node_allocator);
+}
 
-#undef BLOCK_ALLOC_NEXT
-#define BLOCK_ALLOC_NEXT next
+void count_memory_in_node_ss(size_t * num, size_t * size) {
+    struct program_state * state = Pike_compiler;
 
-void free_all_nodes(void)
-{
-  if(!Pike_compiler->previous)
-  {
-    node *tmp;
+    *num = 0;
+    *size = 0;
+
+    while (state) {
+        size_t _num, _size;
+        ba_count_all(&state->node_allocator, &_num, &_size);
+        *num += _num;
+        *size += _size;
+        state = state->previous;
+    }
+}
+
+void node_walker(struct ba_iterator * it, void * data) {
+  do {
+    node * tmp = ba_it_val(it);
+
+    /*
+     * since we free nodes from here, we might iterate over them again.
+     * to avoid that we check for the free mark.
+     */
+    if (tmp->token == USHRT_MAX) continue;
 
-#ifndef PIKE_DEBUG
-    if(cumulative_parse_error) {
-#else
-      size_t e=0, s=0;
-      count_memory_in_node_ss(&e, &s);
-      if(e) {
-#endif
-	WALK_NONFREE_BLOCKS(node_s, tmp, tmp->token != USHRT_MAX, {
 #ifdef PIKE_DEBUG
-	      if(!cumulative_parse_error)
-	      {
-		fprintf(stderr,"Free node at %p, (%s:%ld) (token=%d).\n",
-			(void *)tmp,
-			tmp->current_file->str, (long)tmp->line_number,
-			tmp->token);
+    if(!cumulative_parse_error)
+    {
+      fprintf(stderr,"Free node at %p, (%s:%ld) (token=%d).\n",
+              (void *)tmp,
+              tmp->current_file->str, (long)tmp->line_number,
+              tmp->token);
 
-		debug_malloc_dump_references(tmp,0,2,0);
+      debug_malloc_dump_references(tmp,0,2,0);
 
-		if(tmp->token==F_CONSTANT)
-		  print_tree(tmp);
-	      }
-	      /* else */
+      if(tmp->token==F_CONSTANT)
+        print_tree(tmp);
+    }
+    /* else */
 #endif
-	      {
-		/* Free the node and be happy */
-		/* Make sure we don't free any nodes twice */
-		if(car_is_node(tmp)) _CAR(tmp)=0;
-		if(cdr_is_node(tmp)) _CDR(tmp)=0;
-#ifdef PIKE_DEBUG
-		if (l_flag > 3) {
-		  fprintf(stderr, "Freeing node that had %d refs.\n",
-			  tmp->refs);
-		}
-#endif /* PIKE_DEBUG */
-		/* Force the node to be freed. */
-		tmp->refs = 1;
-		debug_malloc_touch(tmp->type);
-		free_node(tmp);
-	      }
-	});
+    {
+      /* Free the node and be happy */
+      /* Make sure we don't free any nodes twice */
+      if(car_is_node(tmp)) _CAR(tmp)=0;
+      if(cdr_is_node(tmp)) _CDR(tmp)=0;
 #ifdef PIKE_DEBUG
-	if(!cumulative_parse_error)
-	  Pike_fatal("Failed to free %"PRINTSIZET"d nodes when compiling!\n",e);
+      if (l_flag > 3) {
+        fprintf(stderr, "Freeing node that had %d refs.\n",
+                tmp->refs);
       }
-#else
+#endif /* PIKE_DEBUG */
+      /* Force the node to be freed. */
+      tmp->refs = 1;
+      debug_malloc_touch(tmp->type);
+      free_node(tmp);
     }
+  } while (ba_it_step(it));
+}
+
+void free_all_nodes(void)
+{
+  node *tmp;
+
+#ifndef PIKE_DEBUG
+  if(cumulative_parse_error) {
 #endif
-    free_all_node_s_blocks();
-    cumulative_parse_error=0;
+      ba_walk(&Pike_compiler->node_allocator, &node_walker, NULL);
+#ifdef PIKE_DEBUG
+      if(!cumulative_parse_error)
+        Pike_fatal("Failed to free %"PRINTSIZET"d nodes when compiling!\n",e);
+#else
   }
+#endif
+  cumulative_parse_error=0;
 }
 
 void debug_free_node(node *n)
diff --git a/src/las.h b/src/las.h
index 2bbfc8d1f726212d5734f929bc008b14d2b30ca5..63e09cddadb15b491e19e952c9170074188ee9e9 100644
--- a/src/las.h
+++ b/src/las.h
@@ -10,7 +10,7 @@
 #include "global.h"
 #include "svalue.h"
 #include "dynamic_buffer.h"
-#include "block_alloc_h.h"
+#include "block_allocator.h"
 
 #define MAX_GLOBAL_VARIABLES 1000
 typedef void (*c_fun)(INT32);
@@ -154,7 +154,7 @@ struct node_s
 #define SCOPE_SCOPED 2
 #define SCOPE_SCOPE_USED 4
 
-BLOCK_ALLOC_FILL_PAGES(node_s, 2);
+void count_memory_in_node_ss(size_t *num, size_t *size);
 
 /* Prototypes begin here */
 int car_is_node(node *n);
diff --git a/src/program.c b/src/program.c
index 15eb4a1a504e14fd70547a767e9725b386a60670..5c10c2344b74d6a9e510fd72b81cb16bd26ccc8f 100644
--- a/src/program.c
+++ b/src/program.c
@@ -2771,10 +2771,6 @@ void low_start_new_program(struct program *p,
 
   c->compilation_depth++;
 
-  if (!Pike_compiler->compiler_frame) {
-    new_node_s_context();
-  }
-
   SET_SVAL_TYPE(tmp, T_PROGRAM);
   if(!p)
   {
@@ -2826,6 +2822,8 @@ void low_start_new_program(struct program *p,
 #define PUSH
 #include "compilation.h"
 
+  ba_init(&Pike_compiler->node_allocator, sizeof(struct node_s), 512);
+
   Pike_compiler->parent_identifier=id;
   Pike_compiler->compiler_pass = pass;
 
@@ -3315,6 +3313,10 @@ static void toss_compilation_resources(void)
   }
 
   unuse_modules(Pike_compiler->num_used_modules);
+
+  free_all_nodes();
+
+  ba_destroy(&Pike_compiler->node_allocator);
 }
 
 int sizeof_variable(int run_time_type)
@@ -4025,7 +4027,6 @@ struct program *end_first_pass(int finish)
 
   exit_type_stack();
 
-  free_all_nodes();
 
   CDFPRINTF((stderr,
 	     "th(%ld) %p end_first_pass(%d): "
diff --git a/src/program.h b/src/program.h
index 0b0ce0b98eb67aa3ed6e4a89d8825d26119d54e7..0c64c608a927f5cee1aed2f429cb5ad8072b5549 100644
--- a/src/program.h
+++ b/src/program.h
@@ -15,6 +15,7 @@
 #include "time_stuff.h"
 #include "program_id.h"
 #include "pike_rusage.h"
+#include "block_allocator.h"
 
 /* Needed to support dynamic loading on NT */
 PMOD_EXPORT extern struct program_state * Pike_compiler;