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; }