diff --git a/src/code/bytecode.c b/src/code/bytecode.c
index def92e8fb976ebbf4327ca2240d72e073e0d48bc..986fb2531944124ec0beb89abdfc4d59d8cfa36b 100644
--- a/src/code/bytecode.c
+++ b/src/code/bytecode.c
@@ -2,7 +2,7 @@
 || This file is part of Pike. For copyright information see COPYRIGHT.
 || Pike is distributed under GPL, LGPL and MPL. See the file COPYING
 || for more information.
-|| $Id: bytecode.c,v 1.6 2002/10/11 01:39:39 nilsson Exp $
+|| $Id: bytecode.c,v 1.7 2003/11/19 17:19:29 grubba Exp $
 */
 
 /*
@@ -11,11 +11,6 @@
 
 void ins_f_byte(unsigned int b)
 {
-#ifdef PIKE_DEBUG
-  if(store_linenumbers && b<F_MAX_OPCODE)
-    ADD_COMPILED(b);
-#endif /* PIKE_DEBUG */
-
   b-=F_OFFSET;
 #ifdef PIKE_DEBUG
   if(b>255)
diff --git a/src/code/computedgoto.c b/src/code/computedgoto.c
index aa438990c73e4e879e50fc09e559f7705bb801c2..4fbda7ef093fe69bb562c661618dbe0ebefb9af2 100644
--- a/src/code/computedgoto.c
+++ b/src/code/computedgoto.c
@@ -2,7 +2,7 @@
 || This file is part of Pike. For copyright information see COPYRIGHT.
 || Pike is distributed under GPL, LGPL and MPL. See the file COPYING
 || for more information.
-|| $Id: computedgoto.c,v 1.3 2002/10/11 01:39:39 nilsson Exp $
+|| $Id: computedgoto.c,v 1.4 2003/11/19 17:19:29 grubba Exp $
 */
 
 /*
@@ -43,11 +43,6 @@ void ins_data(INT32 val)
 
 void ins_f_byte(unsigned int b)
 {
-#ifdef PIKE_DEBUG
-  if(store_linenumbers && b<F_MAX_OPCODE)
-    ADD_COMPILED(b);
-#endif /* PIKE_DEBUG */
-
   b-=F_OFFSET;
 #ifdef PIKE_DEBUG
   if(b>255)
diff --git a/src/code/ia32.c b/src/code/ia32.c
index 3ce92432e5a6e6bed96ef44690635c01aaf07bf2..ebcc9b1f880e2d354d4d56c33286fec58b0c4a29 100644
--- a/src/code/ia32.c
+++ b/src/code/ia32.c
@@ -2,7 +2,7 @@
 || This file is part of Pike. For copyright information see COPYRIGHT.
 || Pike is distributed under GPL, LGPL and MPL. See the file COPYING
 || for more information.
-|| $Id: ia32.c,v 1.35 2003/08/06 18:08:46 mast Exp $
+|| $Id: ia32.c,v 1.36 2003/11/19 17:19:29 grubba Exp $
 */
 
 /*
@@ -677,10 +677,6 @@ static void ins_debug_instr_prologue (PIKE_INSTR_T instr, INT32 arg1, INT32 arg2
 void ins_f_byte(unsigned int b)
 {
   void *addr;
-#ifdef PIKE_DEBUG
-  if(store_linenumbers && b<F_MAX_OPCODE)
-    ADD_COMPILED(b);
-#endif /* PIKE_DEBUG */
 
   b-=F_OFFSET;
 #ifdef PIKE_DEBUG
diff --git a/src/code/ppc32.c b/src/code/ppc32.c
index 6831e95568f13772e498bed8da65d26ac0d4c3cd..16a360cfdcc757637fa8b44a523e9b3a2bbd16de 100644
--- a/src/code/ppc32.c
+++ b/src/code/ppc32.c
@@ -2,7 +2,7 @@
 || This file is part of Pike. For copyright information see COPYRIGHT.
 || Pike is distributed under GPL, LGPL and MPL. See the file COPYING
 || for more information.
-|| $Id: ppc32.c,v 1.32 2003/08/07 14:45:10 marcus Exp $
+|| $Id: ppc32.c,v 1.33 2003/11/19 17:19:29 grubba Exp $
 */
 
 /*
@@ -397,11 +397,6 @@ void ins_f_byte(unsigned int b)
 {
   void *addr;
 
-#ifdef PIKE_DEBUG
-  if(store_linenumbers && b<F_MAX_OPCODE)
-    ADD_COMPILED(b);
-#endif /* PIKE_DEBUG */
-
   b-=F_OFFSET;
 #ifdef PIKE_DEBUG
   if(b>255)
diff --git a/src/code/sparc.c b/src/code/sparc.c
index 60f413c3c6354d5178113c4899885823711cf2e7..580943a0a33a3517eaccc8cce1760bc7cd6c585c 100644
--- a/src/code/sparc.c
+++ b/src/code/sparc.c
@@ -2,7 +2,7 @@
 || This file is part of Pike. For copyright information see COPYRIGHT.
 || Pike is distributed under GPL, LGPL and MPL. See the file COPYING
 || for more information.
-|| $Id: sparc.c,v 1.37 2003/09/23 17:52:53 grubba Exp $
+|| $Id: sparc.c,v 1.38 2003/11/19 17:19:29 grubba Exp $
 */
 
 /*
@@ -611,11 +611,6 @@ static void low_ins_f_byte(unsigned int b, int delay_ok)
 {
   void *addr;
 
-#ifdef PIKE_DEBUG
-  if(store_linenumbers && b<F_MAX_OPCODE)
-    ADD_COMPILED(b);
-#endif /* PIKE_DEBUG */
-
   b-=F_OFFSET;
 #ifdef PIKE_DEBUG
   if(b>255)
diff --git a/src/docode.c b/src/docode.c
index bdb344b6ecfc0c6b45c5bec5387a5fb14fa88d09..aadd7b226c10d2a82b9c1a7ab27f01a9999b3593 100644
--- a/src/docode.c
+++ b/src/docode.c
@@ -2,11 +2,11 @@
 || This file is part of Pike. For copyright information see COPYRIGHT.
 || Pike is distributed under GPL, LGPL and MPL. See the file COPYING
 || for more information.
-|| $Id: docode.c,v 1.172 2003/11/07 21:29:47 mast Exp $
+|| $Id: docode.c,v 1.173 2003/11/19 17:19:29 grubba Exp $
 */
 
 #include "global.h"
-RCSID("$Id: docode.c,v 1.172 2003/11/07 21:29:47 mast Exp $");
+RCSID("$Id: docode.c,v 1.173 2003/11/19 17:19:29 grubba Exp $");
 #include "las.h"
 #include "program.h"
 #include "pike_types.h"
@@ -184,7 +184,6 @@ INT32 read_int(int offset)
   return EXTRACT_INT(Pike_compiler->new_program->program+offset);
 }
 
-int store_linenumbers=1;
 static int label_no=0;
 
 int alloc_label(void) { return ++label_no; }
@@ -2261,9 +2260,10 @@ static int do_docode2(node *n, int flags)
   }
 }
 
+/* Used to generate code for functions. */
 INT32 do_code_block(node *n)
 {
-  INT32 ret;
+  INT32 entry_point;
 #ifdef PIKE_DEBUG
   if (current_stack_depth != -4711) Pike_fatal("Reentrance in do_code_block().\n");
   current_stack_depth = 0;
@@ -2272,12 +2272,6 @@ INT32 do_code_block(node *n)
   init_bytecode();
   label_no=1;
 
-#ifdef ALIGN_PIKE_FUNCTION_BEGINNINGS
-  while( ( (((INT32) PIKE_PC)+2) & (ALIGN_PIKE_JUMPS-1)))
-    ins_byte(0);
-#endif
-
-  ret=PIKE_PC;
   /* NOTE: This is no ordinary label... */
   low_insert_label(0);
   emit1(F_BYTE,Pike_compiler->compiler_frame->max_number_of_locals);
@@ -2315,17 +2309,18 @@ INT32 do_code_block(node *n)
     emit0(F_START_FUNCTION);
     DO_CODE_BLOCK(n);
   }
-  assemble();
+  entry_point = assemble(1);
 
 #ifdef PIKE_DEBUG
   current_stack_depth = -4711;
 #endif
-  return ret;
+  return entry_point;
 }
 
-int docode(node *n)
+/* Used by eval_low() to build code for constant expressions. */
+INT32 docode(node *n)
 {
-  int tmp;
+  INT32 entry_point;
   int label_no_save = label_no;
   dynamic_buffer instrbuf_save = instrbuf;
   int stack_depth_save = current_stack_depth;
@@ -2339,13 +2334,16 @@ int docode(node *n)
   top_statement_label_dummy.cleanups = 0;	/* please F_PUSH_ARRAY. */
   init_bytecode();
 
-  tmp=do_docode(n,0);
-  assemble();
+  insert_opcode0(F_ENTRY, n->line_number, n->current_file);
+  /* FIXME: Should we check that do_docode() returns 1? */
+  do_docode(n,0);
+  insert_opcode0(F_DUMB_RETURN, n->line_number, n->current_file);
+  entry_point = assemble(0);		/* Don't store linenumbers. */
 
   instrbuf=instrbuf_save;
   label_no = label_no_save;
   current_stack_depth = stack_depth_save;
   current_label = label_save;
   top_statement_label_dummy.cleanups = top_cleanups_save;
-  return tmp;
+  return entry_point;
 }
diff --git a/src/docode.h b/src/docode.h
index 8143def21e16ffd2e062985e5ab9ca7eed70aec8..bc3ee3aa8587a444e7f15fae2a79bd836b2d731b 100644
--- a/src/docode.h
+++ b/src/docode.h
@@ -2,7 +2,7 @@
 || This file is part of Pike. For copyright information see COPYRIGHT.
 || Pike is distributed under GPL, LGPL and MPL. See the file COPYING
 || for more information.
-|| $Id: docode.h,v 1.18 2003/04/02 19:22:42 mast Exp $
+|| $Id: docode.h,v 1.19 2003/11/19 17:19:29 grubba Exp $
 */
 
 #ifndef DOCODE_H
@@ -17,8 +17,6 @@
 
 #define WANT_LVALUE (DO_LVALUE | DO_INDIRECT)
 
-extern int store_linenumbers;
-
 #define emit0(X)     insert_opcode0((X),lex.current_line, lex.current_file)
 #define emit1(X,Y)   insert_opcode1((X),(Y),lex.current_line, lex.current_file)
 #define emit2(X,Y,Z) insert_opcode2((X),(Y),(Z),lex.current_line, lex.current_file)
@@ -35,7 +33,7 @@ void do_pop(int x);
 int do_docode(node *n, int flags);
 void do_cond_jump(node *n, int label, int iftrue, int flags);
 INT32 do_code_block(node *n);
-int docode(node *n);
+INT32 docode(node *n);
 /* Prototypes end here */
 
 #endif
diff --git a/src/las.c b/src/las.c
index 33c060f636c794143e93b45f6f8b1b19e32615a3..9fdcb051650d7d13349c24539ec863984fbea5a3 100644
--- a/src/las.c
+++ b/src/las.c
@@ -2,11 +2,11 @@
 || This file is part of Pike. For copyright information see COPYRIGHT.
 || Pike is distributed under GPL, LGPL and MPL. See the file COPYING
 || for more information.
-|| $Id: las.c,v 1.342 2003/11/14 00:13:36 mast Exp $
+|| $Id: las.c,v 1.343 2003/11/19 17:19:29 grubba Exp $
 */
 
 #include "global.h"
-RCSID("$Id: las.c,v 1.342 2003/11/14 00:13:36 mast Exp $");
+RCSID("$Id: las.c,v 1.343 2003/11/19 17:19:29 grubba Exp $");
 
 #include "language.h"
 #include "interpret.h"
@@ -1391,6 +1391,10 @@ node *debug_mktrampolinenode(int i, struct compiler_frame *frame)
 
 node *debug_mkexternalnode(struct program *parent_prog, int i)
 {
+#if 0
+  return mkidentifiernode(add_ext_ref(Pike_compiler, parent_prog, i));
+
+#else /* !0 */
   struct program_state *state;
   node *res = mkemptynode();
   res->token = F_EXTERNAL;
@@ -1459,6 +1463,7 @@ node *debug_mkexternalnode(struct program *parent_prog, int i)
 #endif
 
   return res;
+#endif /* 0 */
 }
 
 node *debug_mkcastnode(struct pike_type *type, node *n)
@@ -5379,6 +5384,7 @@ static void check_evaluation_time(struct callback *cb,void *tmp,void *ignored)
 ptrdiff_t eval_low(node *n,int print_error)
 {
   unsigned INT16 num_strings, num_constants;
+  unsigned INT32 num_program;
   size_t jump;
   struct svalue *save_sp = Pike_sp;
   ptrdiff_t ret;
@@ -5397,22 +5403,14 @@ ptrdiff_t eval_low(node *n,int print_error)
 
   if(Pike_compiler->num_parse_error) return -1; 
 
-  num_strings=prog->num_strings;
-  num_constants=prog->num_constants;
+  num_strings = prog->num_strings;
+  num_constants = prog->num_constants;
+  num_program = prog->num_program;
 #ifdef PIKE_USE_MACHINE_CODE
   num_relocations = prog->num_relocations;
 #endif /* PIKE_USE_MACHINE_CODE */
 
-  jump = PIKE_PC;
-
-#ifdef INS_ENTRY
-  INS_ENTRY();
-#endif /* INS_ENTRY */
-
-  store_linenumbers=0;
-  docode(dmalloc_touch(node *, n));
-  ins_f_byte(F_DUMB_RETURN);
-  store_linenumbers=1;
+  jump = docode(dmalloc_touch(node *, n));
 
   ret=-1;
   if(!Pike_compiler->num_parse_error)
@@ -5483,12 +5481,12 @@ ptrdiff_t eval_low(node *n,int print_error)
 
 #ifdef VALGRIND_DISCARD_TRANSLATIONS
   /* We won't use this machine code any more... */
-  VALGRIND_DISCARD_TRANSLATIONS(prog->program + jump,
-				(prog->num_program - jump)*sizeof(PIKE_OPCODE_T));
+  VALGRIND_DISCARD_TRANSLATIONS(prog->program + num_program,
+				(prog->num_program - num_program)*sizeof(PIKE_OPCODE_T));
 #endif /* VALGRIND_DISCARD_TRANSLATIONS */
 #endif /* PIKE_USE_MACHINE_CODE */
 
-  prog->num_program=jump;
+  prog->num_program=num_program;
 
   return ret;
 }
diff --git a/src/opcodes.c b/src/opcodes.c
index a3ad1fe1b2da9dddbbc3393fe90b05f5db82ab7c..189864dd8b4e5ba05fa15e10435ca4bd2ef944fd 100644
--- a/src/opcodes.c
+++ b/src/opcodes.c
@@ -2,11 +2,11 @@
 || This file is part of Pike. For copyright information see COPYRIGHT.
 || Pike is distributed under GPL, LGPL and MPL. See the file COPYING
 || for more information.
-|| $Id: opcodes.c,v 1.160 2003/11/17 15:05:49 grubba Exp $
+|| $Id: opcodes.c,v 1.161 2003/11/19 17:19:29 grubba Exp $
 */
 
 #include "global.h"
-RCSID("$Id: opcodes.c,v 1.160 2003/11/17 15:05:49 grubba Exp $");
+RCSID("$Id: opcodes.c,v 1.161 2003/11/19 17:19:29 grubba Exp $");
 #include "constants.h"
 #include "interpret.h"
 #include "opcodes.h"
@@ -402,6 +402,7 @@ void init_opcodes(void)
 
 #ifdef PIKE_USE_MACHINE_CODE
   instrs_checksum = hashmem(instrs, sizeof(instrs), sizeof(instrs));
+  /* fprintf(stderr, "Instruction checksum: %d\n", instrs_checksum); */
 #endif /* PIKE_USE_MACHINE_CODE */
 
 #ifdef PIKE_DEBUG
diff --git a/src/opcodes.h b/src/opcodes.h
index c4cf51d5c0e75e92052ec134f93f360b8987a5b8..da3ccfdba22c79bc892307823f7dd82481ddaea7 100644
--- a/src/opcodes.h
+++ b/src/opcodes.h
@@ -2,7 +2,7 @@
 || This file is part of Pike. For copyright information see COPYRIGHT.
 || Pike is distributed under GPL, LGPL and MPL. See the file COPYING
 || for more information.
-|| $Id: opcodes.h,v 1.37 2003/11/17 14:39:48 grubba Exp $
+|| $Id: opcodes.h,v 1.38 2003/11/19 17:19:29 grubba Exp $
 */
 
 #ifndef OPCODES_H
@@ -241,7 +241,11 @@ enum Pike_opcodes
   /* Alias for F_RETURN, but cannot be optimized into a tail recursion call */
   F_VOLATILE_RETURN,
 
-  F_MAX_INSTR
+  F_MAX_INSTR,
+
+  /* These are only used for dumping. */
+  F_FILENAME,
+  F_LINE,
 };
 
 #undef OPCODE0
diff --git a/src/peep.c b/src/peep.c
index fcd5903bd3b0f8322c66446e694c0cf01226dbcc..8948cca933bfd2567cc0a48e81c324946578afc1 100644
--- a/src/peep.c
+++ b/src/peep.c
@@ -2,7 +2,7 @@
 || This file is part of Pike. For copyright information see COPYRIGHT.
 || Pike is distributed under GPL, LGPL and MPL. See the file COPYING
 || for more information.
-|| $Id: peep.c,v 1.92 2003/10/17 03:49:26 nilsson Exp $
+|| $Id: peep.c,v 1.93 2003/11/19 17:19:29 grubba Exp $
 */
 
 #include "global.h"
@@ -26,7 +26,7 @@
 #include "interpret.h"
 #include "pikecode.h"
 
-RCSID("$Id: peep.c,v 1.92 2003/10/17 03:49:26 nilsson Exp $");
+RCSID("$Id: peep.c,v 1.93 2003/11/19 17:19:29 grubba Exp $");
 
 static void asm_opt(void);
 
@@ -147,13 +147,17 @@ void update_arg(int instr,INT32 arg)
 
 /**** Bytecode Generator *****/
 
-void assemble(void)
+INT32 assemble(int store_linenumbers)
 {
+  INT32 entry_point;
   INT32 max_label=-1,tmp;
   INT32 *labels, *jumps, *uses;
   ptrdiff_t e, length;
   p_instr *c;
   int reoptimize=!(debug_options & NO_PEEP_OPTIMIZING);
+#ifdef PIKE_PORTABLE_BYTECODE
+  struct pike_tripple *tripples = NULL;
+#endif /* PIKE_PORTABLE_BYTECODE */
 #ifdef PIKE_DEBUG
   INT32 max_pointer=-1;
   int synch_depth = 0;
@@ -180,6 +184,68 @@ void assemble(void)
   }
 #endif
 
+#ifdef PIKE_PORTABLE_BYTECODE
+  /* No need to do this for constant evaluations. */
+  if (store_linenumbers) {
+    struct pike_tripple *current_tripple;
+    struct pike_string *previous_file = NULL;
+    int previous_line = 0;
+    ptrdiff_t num_linedirectives = 0;
+
+    /* Count the number of F_FILE/F_LINE pseudo-ops we need to add. */
+    for (e=0; e < length; e++) {
+      if (c[e].file != previous_file) {
+	previous_file = c[e].file;
+	num_linedirectives++;
+      }
+      if (c[e].line != previous_line) {
+	previous_line = c[e].line;
+	num_linedirectives++;
+      }
+    }
+
+    fprintf(stderr, "length:%d directives:%d\n", length, num_linedirectives);
+      
+    if (!(tripples = malloc(sizeof(struct pike_tripple) *
+			    (length+num_linedirectives)))) {
+      Pike_fatal("Failed to allocate %d tripples (%d + %d).\n",
+		 length+num_linedirectives, length, num_linedirectives);
+    }
+    previous_file = NULL;
+    previous_line = 0;
+    current_tripple = tripples;
+    for (e = 0; e < length; e++) {
+      if (c[e].file != previous_file) {
+	current_tripple->opcode = F_FILENAME;
+	current_tripple->arg = store_prog_string(c[e].file);
+	current_tripple->arg2 = 0;
+	current_tripple++;
+	previous_file = c[e].file;
+      }
+      if (c[e].line != previous_line) {
+	current_tripple->opcode = F_LINE;
+	current_tripple->arg = c[e].line;
+	current_tripple->arg2 = 0;
+	current_tripple++;
+	previous_line = c[e].line;
+      }
+      current_tripple->opcode = c[e].opcode;
+      current_tripple->arg = c[e].arg;
+      current_tripple->arg2 = c[e].arg2;
+      current_tripple++;
+    }
+#ifdef PIKE_DEBUG
+    if (current_tripple != tripples + length + num_linedirectives) {
+      Pike_fatal("Tripple length mismatch %d != %d (%d + %d)\n",
+		 current_tripple - tripples,
+		 length + num_linedirectives,
+		 length, num_linedirectives);
+    }
+#endif /* PIKE_DEBUG */
+  }
+  
+#endif /* PIKE_PORTABLE_BYTECODE */
+
   for(e=0;e<length;e++,c++) {
     if(c->opcode == F_LABEL) {
       if(c->arg > max_label)
@@ -321,11 +387,28 @@ void assemble(void)
 #endif /* 1 */
   }
 
+  /* Time to create the actual bytecode. */
+
   c=(p_instr *)instrbuf.s.str;
   length=instrbuf.s.len / sizeof(p_instr);
 
   for(e=0;e<=max_label;e++) labels[e]=jumps[e]=-1;
   
+#ifdef ALIGN_PIKE_FUNCTION_BEGINNINGS
+  while( ( (((INT32) PIKE_PC)+2) & (ALIGN_PIKE_JUMPS-1)))
+    ins_byte(0);
+#endif
+
+#ifdef PIKE_PORTABLE_BYTECODE
+  if (store_linenumbers) {
+    ins_pointer(tripples);
+  } else {
+    ins_pointer(NULL);
+  }
+#endif /* PIKE_PORTABLE_BYTECODE */
+
+  entry_point = PIKE_PC;
+
 #ifdef PIKE_DEBUG
   synch_depth = 0;
 #endif
@@ -348,8 +431,13 @@ void assemble(void)
     }
 #endif
 
-    if(store_linenumbers)
+    if(store_linenumbers) {
       store_linenumber(c->line, c->file);
+#ifdef PIKE_DEBUG
+      if (c->opcode < F_MAX_OPCODE)
+	ADD_COMPILED(c->opcode);
+#endif /* PIKE_DEBUG */
+    }
 
     switch(c->opcode)
     {
@@ -618,6 +706,8 @@ void assemble(void)
 #endif /* PIKE_DEBUG */
 
   exit_bytecode();
+
+  return entry_point;
 }
 
 /**** Peephole optimizer ****/
diff --git a/src/peep.h b/src/peep.h
index 943d133a52bcfbc84464b81556e32ecb8fd1dc1d..567571b1e134eea35195b5955d445b831aefedb9 100644
--- a/src/peep.h
+++ b/src/peep.h
@@ -2,7 +2,7 @@
 || This file is part of Pike. For copyright information see COPYRIGHT.
 || Pike is distributed under GPL, LGPL and MPL. See the file COPYING
 || for more information.
-|| $Id: peep.h,v 1.13 2002/11/01 16:59:07 grubba Exp $
+|| $Id: peep.h,v 1.14 2003/11/19 17:19:29 grubba Exp $
 */
 
 #ifndef PEEP_H
@@ -37,7 +37,7 @@ ptrdiff_t insert_opcode1(unsigned int f,
 ptrdiff_t insert_opcode0(int f,int current_line,
 			 struct pike_string *current_file);
 void update_arg(int instr,INT32 arg);
-void assemble(void);
+INT32 assemble(int store_linenumbers);
 /* Prototypes end here */
 
 #endif