diff --git a/src/docode.c b/src/docode.c
index 299d171fc856484066c8a33c261a136878811bb5..2251f3cd5130b91c1eb1e19a03ddbc30e0907f26 100644
--- a/src/docode.c
+++ b/src/docode.c
@@ -5,7 +5,7 @@
 \*/
 /**/
 #include "global.h"
-RCSID("$Id: docode.c,v 1.70 2000/04/30 23:15:16 hubbe Exp $");
+RCSID("$Id: docode.c,v 1.71 2000/05/01 02:11:25 hubbe Exp $");
 #include "las.h"
 #include "program.h"
 #include "language.h"
@@ -205,14 +205,22 @@ int do_lfun_call(int id,node *args)
 #if 1
   if(id == compiler_frame->current_function_number)
   {
-    if(new_program->identifier_references[id].id_flags & ID_INLINE)
+    int n=count_args(args);
+    if(n == compiler_frame->num_args)
     {
-      int n=count_args(args);
-      if(n == count_arguments(ID_FROM_INT(new_program, id) -> type))
+      if(compiler_frame->is_inline)
       {
 	emit0(F_MARK);
 	do_docode(args,0);
-	emit1(F_RECUR,0); /* 0 is label at beginning of function */
+	compiler_frame->recur_label=do_jump(F_RECUR,
+					    compiler_frame->recur_label);
+	return 1;
+      }else{
+	emit0(F_MARK);
+	do_docode(args,0);
+	emit1(F_COND_RECUR,id);
+	compiler_frame->recur_label=do_jump(F_POINTER,
+					    compiler_frame->recur_label);
 	return 1;
       }
     }
@@ -1296,8 +1304,40 @@ void do_code_block(node *n)
 {
   init_bytecode();
   label_no=1;
+
+  emit1(F_BYTE,compiler_frame->max_number_of_locals);
+  emit1(F_BYTE,compiler_frame->num_args);
+  emit0(F_START_FUNCTION);
   emit1(F_LABEL,0);
+  if(new_program->identifier_references[compiler_frame->
+				       current_function_number].id_flags &
+     ID_INLINE)
+  {
+    compiler_frame->recur_label=0;
+    compiler_frame->is_inline=1;
+  }
+
   DO_CODE_BLOCK(n);
+
+  if(compiler_frame->recur_label > 0)
+  {
+#ifdef PIKE_DEBUG
+    if(l_flag)
+    {
+      fprintf(stderr,"Generating inline recursive function.\n");
+    }
+#endif
+    /* generate code again, but this time it is inline */
+    compiler_frame->is_inline=1;
+
+    /* This is a no-op, but prevents optimizer to delete the bytes below */
+    emit1(F_LABEL,-1);
+    emit1(F_BYTE,compiler_frame->max_number_of_locals);
+    emit1(F_BYTE,compiler_frame->num_args);
+    emit0(F_START_FUNCTION);
+    emit1(F_LABEL,compiler_frame->recur_label);
+    DO_CODE_BLOCK(n);
+  }
   assemble();
 }
 
diff --git a/src/interpret_functions.h b/src/interpret_functions.h
index c42eb8ada407d0e1ffacb980d375e88a5c04958b..0a41679e7153df284861871af82d59dc91604d45 100644
--- a/src/interpret_functions.h
+++ b/src/interpret_functions.h
@@ -1,5 +1,5 @@
 /*
- * $Id: interpret_functions.h,v 1.18 2000/04/30 23:15:16 hubbe Exp $
+ * $Id: interpret_functions.h,v 1.19 2000/05/01 02:11:25 hubbe Exp $
  *
  * Opcode definitions for the interpreter.
  */
@@ -1429,27 +1429,27 @@ OPCODE1(F_SSCANF, "sscanf")
   o_sscanf(arg1);
 BREAK;
 
-      CASE(F_CALL_LFUN);
-      apply_low(Pike_fp->current_object,
-		GET_ARG()+Pike_fp->context.identifier_level,
-		Pike_sp - *--Pike_mark_sp);
-      break;
+OPCODE1(F_CALL_LFUN,"call lfun")
+  apply_low(Pike_fp->current_object,
+	    arg1+Pike_fp->context.identifier_level,
+	    Pike_sp - *--Pike_mark_sp);
+BREAK;
 
-      CASE(F_CALL_LFUN_AND_POP);
-      apply_low(Pike_fp->current_object,
-		GET_ARG()+Pike_fp->context.identifier_level,
-		Pike_sp - *--Pike_mark_sp);
-      pop_stack();
-      break;
+OPCODE1(F_CALL_LFUN_AND_POP,"call lfun & pop")
+  apply_low(Pike_fp->current_object,
+            arg1+Pike_fp->context.identifier_level,
+            Pike_sp - *--Pike_mark_sp);
+  pop_stack();
+BREAK;
 
-    CASE(F_MARK_APPLY);
-      strict_apply_svalue(Pike_fp->context.prog->constants + GET_ARG(), 0);
-      break;
+OPCODE1(F_MARK_APPLY,"mark apply")
+ strict_apply_svalue(Pike_fp->context.prog->constants + arg1, 0);
+BREAK;
 
-    CASE(F_MARK_APPLY_POP);
-      strict_apply_svalue(Pike_fp->context.prog->constants + GET_ARG(), 0);
-      pop_stack();
-      break;
+OPCODE1(F_MARK_APPLY_POP,"mark, apply & pop")
+  strict_apply_svalue(Pike_fp->context.prog->constants + arg1, 0);
+  pop_stack();
+BREAK;
 
     CASE(F_APPLY);
       strict_apply_svalue(Pike_fp->context.prog->constants + GET_ARG(), Pike_sp - *--Pike_mark_sp );
@@ -1503,11 +1503,11 @@ OPCODE0_JUMP(F_RECUR,"recur")
   save_mark_sp=mark_sp;
 
   addr=pc+EXTRACT_INT(pc);
-  num_locals=EXTRACT_UCHAR(addr-1);
+  num_locals=EXTRACT_UCHAR(addr-2);
 
 #ifdef PIKE_DEBUG
-  if(args != EXTRACT_UCHAR(addr-2))
-    fatal("Wrong number of arguments in F_RECUR %d!=%d\n",args,EXTRACT_UCHAR(addr-2));
+  if(args != EXTRACT_UCHAR(addr-1))
+    fatal("Wrong number of arguments in F_RECUR %d!=%d\n",args,EXTRACT_UCHAR(addr-1));
 #endif
 
   clear_svalues(sp, num_locals - args);
@@ -1532,6 +1532,61 @@ OPCODE0_JUMP(F_RECUR,"recur")
 }
 BREAK
 
+/* Assume that the number of arguments is correct */
+OPCODE1_JUMP(F_COND_RECUR,"recur if not overloaded")
+{
+  int x,num_locals,args;
+  char *addr;
+
+  struct svalue *expendible=fp->expendible;
+  struct svalue *locals=fp->locals;
+  struct svalue *save_sp, **save_mark_sp;
+
+  if(fp->current_object->prog != fp->context.prog)
+  {
+    apply_low(Pike_fp->current_object,
+	      arg1+Pike_fp->context.identifier_level,
+	      Pike_sp - *--Pike_mark_sp);
+  }else{
+    fast_check_threads_etc(6);
+    check_c_stack(8192);
+    check_stack(256);
+    
+    save_sp=fp->expendible=fp->locals=*--Pike_mark_sp;
+    args=sp-fp->locals;
+    save_mark_sp=mark_sp;
+    
+    addr=pc+EXTRACT_INT(pc);
+    num_locals=EXTRACT_UCHAR(addr-2);
+    
+#ifdef PIKE_DEBUG
+    if(args != EXTRACT_UCHAR(addr-1))
+      fatal("Wrong number of arguments in F_RECUR %d!=%d\n",args,EXTRACT_UCHAR(addr-1));
+#endif
+    
+    clear_svalues(sp, num_locals - args);
+    sp += num_locals - args;
+    
+    x=eval_instruction(addr);
+    mark_sp=save_mark_sp;
+    if(x!=-1) mega_apply(APPLY_STACK, x, 0,0);
+    pc+=sizeof(INT32);
+    if(save_sp+1 < sp)
+    {
+      assign_svalue(save_sp,sp-1);
+      pop_n_elems(sp-save_sp-1);
+    }
+    fp->expendible=expendible;
+    fp->locals=locals;
+    print_return_value();
+#ifdef PIKE_DEBUG
+    if(sp != save_sp+1)
+      fatal("Stack whack in F_RECUR sp=%p, expected=%p\n",sp,save_sp+1);
+#endif
+  }
+}
+BREAK
+
 /* Assume that the number of arguments is correct */
 OPCODE0_JUMP(F_TAIL_RECUR,"tail recursion")
 {
@@ -1542,12 +1597,12 @@ OPCODE0_JUMP(F_TAIL_RECUR,"tail recursion")
   fast_check_threads_etc(6);
 
   addr=pc+EXTRACT_INT(pc);
-  num_locals=EXTRACT_UCHAR(addr-1);
+  num_locals=EXTRACT_UCHAR(addr-2);
 
 
 #ifdef PIKE_DEBUG
-  if(args != EXTRACT_UCHAR(addr-2))
-    fatal("Wrong number of arguments in F_TAIL_RECUR %d != %d\n",args,EXTRACT_UCHAR(addr-2));
+  if(args != EXTRACT_UCHAR(addr-1))
+    fatal("Wrong number of arguments in F_TAIL_RECUR %d != %d\n",args,EXTRACT_UCHAR(addr-1));
 #endif
 
   if(sp-args != fp->locals)
diff --git a/src/language.yacc b/src/language.yacc
index 95083e795aacf870408229794d3f7d7f2820b74d..f993d4b104b7d62db1176905b7074a4c09629f5b 100644
--- a/src/language.yacc
+++ b/src/language.yacc
@@ -33,7 +33,7 @@
 %token F_BRANCH_IF_NOT_LOCAL_ARROW
 %token F_INC_LOOP F_DEC_LOOP
 %token F_INC_NEQ_LOOP F_DEC_NEQ_LOOP
-%token F_RECUR F_TAIL_RECUR
+%token F_RECUR F_TAIL_RECUR F_COND_RECUR
 
 %token F_LEXICAL_LOCAL F_LEXICAL_LOCAL_LVALUE
 
@@ -171,6 +171,8 @@
 %token F_POINTER
 %token F_LABEL
 %token F_DATA
+%token F_START_FUNCTION
+%token F_BYTE
 
 %token F_MAX_INSTR
 
@@ -193,7 +195,7 @@
 /* This is the grammar definition of Pike. */
 
 #include "global.h"
-RCSID("$Id: language.yacc,v 1.181 2000/04/25 09:32:46 hubbe Exp $");
+RCSID("$Id: language.yacc,v 1.182 2000/05/01 02:11:25 hubbe Exp $");
 #ifdef HAVE_MEMORY_H
 #include <memory.h>
 #endif
diff --git a/src/las.c b/src/las.c
index dfc198978c28f763e630039ab56c1e6c14dd9bbd..c5e13b16ffe47c4e4754de570eca4e57db961a98 100644
--- a/src/las.c
+++ b/src/las.c
@@ -5,7 +5,7 @@
 \*/
 /**/
 #include "global.h"
-RCSID("$Id: las.c,v 1.175 2000/04/15 05:05:28 hubbe Exp $");
+RCSID("$Id: las.c,v 1.176 2000/05/01 02:11:25 hubbe Exp $");
 
 #include "language.h"
 #include "interpret.h"
@@ -3930,8 +3930,7 @@ int dooptcode(struct pike_string *name,
     }
 
     tmp.offset=PC;
-    add_to_program(compiler_frame->max_number_of_locals);
-    add_to_program(args);
+    compiler_frame->num_args=args;
   
 #ifdef PIKE_DEBUG
     if(a_flag > 2)
diff --git a/src/las.h b/src/las.h
index 286dc591de23c80e9ece75f802dbfaee06aa1f1c..88e759fcf365e8b842f4227fd99a84f93e0c05c7 100644
--- a/src/las.h
+++ b/src/las.h
@@ -5,7 +5,7 @@
 \*/
 
 /*
- * $Id: las.h,v 1.35 2000/04/25 09:32:46 hubbe Exp $
+ * $Id: las.h,v 1.36 2000/05/01 02:11:25 hubbe Exp $
  */
 #ifndef LAS_H
 #define LAS_H
@@ -51,8 +51,11 @@ struct compiler_frame
   struct pike_string *current_return_type;
   int current_number_of_locals;
   int max_number_of_locals;
+  int num_args;
   int lexical_scope;
   int current_function_number;
+  int recur_label;
+  int is_inline;
   struct local_variable variable[MAX_LOCAL];
 };
 
diff --git a/src/lex.c b/src/lex.c
index 26c1a1eb5170f84af989ca7e59a15d0b9d5d72fe..3b68bb14fc5e785482db4924fd3a7baea2a70db7 100644
--- a/src/lex.c
+++ b/src/lex.c
@@ -5,7 +5,7 @@
 \*/
 /**/
 #include "global.h"
-RCSID("$Id: lex.c,v 1.78 2000/04/25 09:32:46 hubbe Exp $");
+RCSID("$Id: lex.c,v 1.79 2000/05/01 02:11:25 hubbe Exp $");
 #include "language.h"
 #include "array.h"
 #include "lex.h"
@@ -154,9 +154,8 @@ struct keyword instr_names[]=
 { "foreach",		F_FOREACH, I_ISJUMP },
 { "pointer",		F_POINTER, I_ISPOINTER },
 { "data",		F_DATA, I_DATA },
+{ "byte",		F_BYTE, I_DATA },
 
-{ "local function call",F_CALL_LFUN, I_HASARG },
-{ "local function call and pop",F_CALL_LFUN_AND_POP, I_HASARG },
 { "lvalue_list",	F_LVALUE_LIST,0 },	
 { "return",		F_RETURN,0 },
 { "return 0",		F_RETURN_0,0 },
@@ -171,8 +170,7 @@ struct keyword instr_names[]=
 { "-int index",         F_NEG_INT_INDEX, I_HASARG },
 { "apply and pop",      F_APPLY_AND_POP, I_HASARG },
 { "nop",                F_NOP,0 },
-{ "mark & call",        F_MARK_APPLY, I_HASARG },
-{ "mark, call & pop",   F_MARK_APPLY_POP, I_HASARG },
+{ "function start",     F_START_FUNCTION,0 },
 { "apply and return",   F_APPLY_AND_RETURN, I_HASARG },
 { "call function",      F_CALL_FUNCTION, 0 },
 { "call function & return", F_CALL_FUNCTION_AND_RETURN, 0 },
diff --git a/src/peep.c b/src/peep.c
index 93f4c2a7aae5e2d615a52290d4745602f3086f1e..c5ac90692af19cd3ca94f55f948cfb72c018faef 100644
--- a/src/peep.c
+++ b/src/peep.c
@@ -14,7 +14,7 @@
 #include "stuff.h"
 #include "bignum.h"
 
-RCSID("$Id: peep.c,v 1.31 2000/04/21 00:29:48 hubbe Exp $");
+RCSID("$Id: peep.c,v 1.32 2000/05/01 02:11:25 hubbe Exp $");
 
 struct p_instr_s
 {
@@ -246,7 +246,7 @@ void assemble(void)
 
   c=(p_instr *)instrbuf.s.str;
   for(e=0;e<length;e++)
-    if(c[e].opcode == F_LABEL)
+    if(c[e].opcode == F_LABEL && c[e].arg>=0)
       labels[c[e].arg]=e;
 
   for(e=0;e<length;e++)
@@ -320,16 +320,23 @@ void assemble(void)
 
     switch(c->opcode)
     {
-    case F_NOP: break;
+    case F_NOP:
+    case F_START_FUNCTION:
+      break;
     case F_ALIGN:
       while(PC % c->arg) add_to_program(0);
       break;
 
+    case F_BYTE:
+      add_to_program(c->arg);
+      break;
+
     case F_DATA:
       ins_int(c->arg, (void(*)(char))add_to_program);
       break;
 
     case F_LABEL:
+      if(c->arg == -1) break;
 #ifdef PIKE_DEBUG
       if(c->arg > max_label || c->arg < 0)
 	fatal("max_label calculation failed!\n");
@@ -385,7 +392,7 @@ void assemble(void)
     {
 #ifdef PIKE_DEBUG
       if(labels[e]==-1)
-	fatal("Hyperspace error: unknown jump point %d at %d (%d).\n",e,labels[e],jumps[e]);
+	fatal("Hyperspace error: unknown jump point %d at %d (pc=%x).\n",e,labels[e],jumps[e]);
 #endif
       tmp=read_int(jumps[e]);
       upd_int(jumps[e], tmp2 - jumps[e]);
diff --git a/src/peep.in b/src/peep.in
index 15652e74a4113aa2e699d30e8b7251585f8d897b..87465fc862aa85c27a64a957dd6f8da4a6a9215a 100644
--- a/src/peep.in
+++ b/src/peep.in
@@ -1,5 +1,5 @@
 //
-// $Id: peep.in,v 1.34 2000/04/30 23:15:16 hubbe Exp $
+// $Id: peep.in,v 1.35 2000/05/01 02:11:25 hubbe Exp $
 //
 
 NOP :
@@ -35,9 +35,13 @@ NEGATE CONST1 SUBTRACT : COMPL
 CONST0 ASSIGN_LOCAL_AND_POP : CLEAR_LOCAL($2a)
 
 // Remove clearing of locals from the beginning of functions
-CLEAR_LOCAL [(fifo_len == (long)instrbuf.s.len / (long)sizeof(p_instr)) && $1a>=remove_clear_locals] : 
-CLEAR_2_LOCAL [(fifo_len == (long)instrbuf.s.len / (long)sizeof(p_instr)) && $1a>=remove_clear_locals] : 
-CLEAR_4_LOCAL [(fifo_len == (long)instrbuf.s.len / (long)sizeof(p_instr)) && $1a>=remove_clear_locals] : 
+START_FUNCTION LABEL(0) CLEAR_LOCAL : LABEL(0)
+START_FUNCTION LABEL(0) CLEAR_2_LOCAL : LABEL(0)
+START_FUNCTION LABEL(0) CLEAR_4_LOCAL : LABEL(0)
+
+START_FUNCTION CLEAR_LOCAL :
+START_FUNCTION CLEAR_2_LOCAL :
+START_FUNCTION CLEAR_4_LOCAL :
 
 CLEAR_LOCAL NUMBER(0) ASSIGN_LOCAL_AND_POP ($1a) : CLEAR_LOCAL($1a)
 CLEAR_LOCAL NUMBER(0) ASSIGN_LOCAL_AND_POP ($1a+1) : CLEAR_2_LOCAL($1a)
@@ -297,7 +301,9 @@ TRAMPOLINE POP_VALUE :
 
 
 RECUR RETURN: TAIL_RECUR ($1a)
-MARK TAIL_RECUR : BRANCH ($1a)
+
+// This doesn't really work
+// MARK TAIL_RECUR : BRANCH ($1a)
 
 ASSIGN_LOCAL BRANCH_WHEN_ZERO 2_LOCALS(,$1a) BRANCH_WHEN_EQ : ASSIGN_LOCAL($1a) BRANCH_AND_POP_WHEN_ZERO($2a) LOCAL($3a) BRANCH_WHEN_EQ($4a)
 ASSIGN_LOCAL BRANCH_WHEN_ZERO 2_LOCALS(,$1a) BRANCH_WHEN_NE : ASSIGN_LOCAL($1a) BRANCH_AND_POP_WHEN_ZERO($2a) LOCAL($3a) BRANCH_WHEN_NE($4a)
diff --git a/src/program.c b/src/program.c
index f0665b8d5314c98b8e94d3e1d011e6c62c479dd3..1806d40a8a71d88523163b32d9deb088f5887c6b 100644
--- a/src/program.c
+++ b/src/program.c
@@ -5,7 +5,7 @@
 \*/
 /**/
 #include "global.h"
-RCSID("$Id: program.c,v 1.234 2000/04/27 02:13:28 hubbe Exp $");
+RCSID("$Id: program.c,v 1.235 2000/05/01 02:11:25 hubbe Exp $");
 #include "program.h"
 #include "object.h"
 #include "dynamic_buffer.h"
@@ -3671,6 +3671,9 @@ void push_compiler_frame(int lexical_scope)
   f->max_number_of_locals=0;
   f->previous=compiler_frame;
   f->current_function_number=-2; /* no function */
+  f->recur_label=-1;
+  f->is_inline=0;
+  f->num_args=-1;
   compiler_frame=f;
 }