diff --git a/src/docode.c b/src/docode.c index 62343a50fd519db008efd348fb6e4d0c2bdb11c4..52b7c01d08a646f691b8bc60118746672a3399e9 100644 --- a/src/docode.c +++ b/src/docode.c @@ -5,7 +5,7 @@ \*/ /**/ #include "global.h" -RCSID("$Id: docode.c,v 1.68 2000/04/20 02:41:44 hubbe Exp $"); +RCSID("$Id: docode.c,v 1.69 2000/04/25 09:32:45 hubbe Exp $"); #include "las.h" #include "program.h" #include "language.h" @@ -200,6 +200,30 @@ static inline struct compiler_frame *find_local_frame(INT32 depth) return f; } +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 == count_arguments(ID_FROM_INT(new_program, id) -> type)) + { + emit0(F_MARK); + do_docode(args,0); + emit1(F_RECUR,0); /* 0 is label at beginning of function */ + return 1; + } + } + } +#endif + emit0(F_MARK); + do_docode(args,0); + emit1(F_CALL_LFUN, id); + return 1; +} + static int do_docode2(node *n,int flags) { INT32 tmp1,tmp2,tmp3; @@ -743,12 +767,7 @@ static int do_docode2(node *n,int flags) return 1; }else{ if(CAR(n)->u.sval.u.object == fake_object) - { - emit0(F_MARK); - do_docode(CDR(n),0); - emit1(F_CALL_LFUN, CAR(n)->u.sval.subtype); - return 1; - } + return do_lfun_call(CAR(n)->u.sval.subtype,CDR(n)); } } @@ -762,12 +781,10 @@ static int do_docode2(node *n,int flags) return 1; } else if(CAR(n)->token == F_IDENTIFIER && - IDENTIFIER_IS_FUNCTION(ID_FROM_INT(new_program, CAR(n)->u.id.number)->identifier_flags)) + IDENTIFIER_IS_FUNCTION(ID_FROM_INT(new_program, + CAR(n)->u.id.number)->identifier_flags)) { - emit0(F_MARK); - do_docode(CDR(n),0); - emit1(F_CALL_LFUN, CAR(n)->u.id.number); - return 1; + return do_lfun_call(CAR(n)->u.id.number,CDR(n)); } else { @@ -1277,7 +1294,8 @@ static int do_docode2(node *n,int flags) void do_code_block(node *n) { init_bytecode(); - label_no=0; + label_no=1; + emit1(F_LABEL,0); DO_CODE_BLOCK(n); assemble(); } @@ -1289,7 +1307,7 @@ int docode(node *n) dynamic_buffer instrbuf_save = instrbuf; instrbuf.s.str=0; - label_no=0; + label_no=1; init_bytecode(); tmp=do_docode(n,0); diff --git a/src/interpret.c b/src/interpret.c index 9e9910531b176f180251c0957f71ea916a62c5c9..777e81e25a7a7dbb7c213079770f5a5eadfefd3d 100644 --- a/src/interpret.c +++ b/src/interpret.c @@ -5,7 +5,7 @@ \*/ /**/ #include "global.h" -RCSID("$Id: interpret.c,v 1.147 2000/04/21 23:07:10 hubbe Exp $"); +RCSID("$Id: interpret.c,v 1.148 2000/04/25 09:32:46 hubbe Exp $"); #include "interpret.h" #include "object.h" #include "program.h" @@ -1068,10 +1068,8 @@ void mega_apply2(enum apply_type type, INT32 args, void *arg1, void *arg2) num_locals=EXTRACT_UCHAR(pc++); num_args=EXTRACT_UCHAR(pc++); - /* FIXME: this is only needed if this function contains - * trampolines - */ - new_frame->expendible+=num_locals; + if(function->identifier_flags & IDENTIFIER_SCOPED) + new_frame->expendible+=num_locals; /* adjust arguments on stack */ if(args < num_args) /* push zeros */ diff --git a/src/interpret_functions.h b/src/interpret_functions.h index e9903ee4d89e91de956f544b7797764a7c06529e..7fd30b9027902c287511e839afaba9b1de0cc723 100644 --- a/src/interpret_functions.h +++ b/src/interpret_functions.h @@ -1,5 +1,5 @@ /* - * $Id: interpret_functions.h,v 1.15 2000/04/21 00:29:48 hubbe Exp $ + * $Id: interpret_functions.h,v 1.16 2000/04/25 09:32:46 hubbe Exp $ * * Opcode definitions for the interpreter. */ @@ -996,29 +996,31 @@ BREAK; return args+1; } - CASE(F_CALL_LFUN_AND_RETURN); - { - INT32 args=Pike_sp - *--Pike_mark_sp; - if(Pike_fp->expendible >= Pike_sp-args) - { - MEMMOVE(Pike_sp-args+1,Pike_sp-args,args*sizeof(struct svalue)); - Pike_sp++; - Pike_sp[-args-1].type=PIKE_T_INT; - }else{ - free_svalue(Pike_sp-args-1); - } - /* More stack sabotage */ - Pike_sp[-args-1].u.object=Pike_fp->current_object; - Pike_sp[-args-1].subtype=GET_ARG()+Pike_fp->context.identifier_level; +OPCODE1(F_CALL_LFUN_AND_RETURN,"call lfun & return") +{ + INT32 args=sp - *--Pike_mark_sp; + + if(Pike_fp->expendible >= Pike_sp-args) + { + MEMMOVE(Pike_sp-args+1,Pike_sp-args,args*sizeof(struct svalue)); + Pike_sp++; + Pike_sp[-args-1].type=PIKE_T_INT; + }else{ + free_svalue(Pike_sp-args-1); + } + /* More stack sabotage */ + Pike_sp[-args-1].u.object=Pike_fp->current_object; + Pike_sp[-args-1].subtype=arg1+Pike_fp->context.identifier_level; #ifdef PIKE_DEBUG - if(t_flag > 9) - fprintf(stderr,"- IDENTIFIER_LEVEL: %d\n",Pike_fp->context.identifier_level); + if(t_flag > 9) + fprintf(stderr,"- IDENTIFIER_LEVEL: %d\n",Pike_fp->context.identifier_level); #endif - Pike_sp[-args-1].type=PIKE_T_FUNCTION; - add_ref(Pike_fp->current_object); - - return args+1; - } + Pike_sp[-args-1].type=PIKE_T_FUNCTION; + add_ref(Pike_fp->current_object); + + return args+1; +} +BREAK CASE(F_RETURN_LOCAL); instr=GET_ARG(); @@ -1157,13 +1159,31 @@ OPCODE0(F_MOD, "%") BREAK; OPCODE1(F_ADD_INT, "add integer") - push_int(arg1); - f_add(2); + if(sp[-1].type == T_INT +#ifdef AUTO_BIGNUM + && (!INT_TYPE_ADD_OVERFLOW(sp[-1].u.integer, arg1)) +#endif + ) + { + sp[-1].u.integer+=arg1; + }else{ + push_int(arg1); + f_add(2); + } BREAK; OPCODE1(F_ADD_NEG_INT, "add -integer") - push_int(-arg1); - f_add(2); + if(sp[-1].type == T_INT +#ifdef AUTO_BIGNUM + && (!INT_TYPE_ADD_OVERFLOW(sp[-1].u.integer, -arg1)) +#endif + ) + { + sp[-1].u.integer-=arg1; + }else{ + push_int(-arg1); + f_add(2); + } BREAK; OPCODE0(F_PUSH_ARRAY, "@") @@ -1464,3 +1484,84 @@ BREAK; return args; } + +/* Assume that the number of arguments is correct */ +OPCODE0_JUMP(F_RECUR,"recur") +{ + int x,num_locals,args; + char *addr; + struct svalue *expendible=fp->expendible; + struct svalue *locals=fp->locals; + struct svalue *save_sp; + + 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; + + addr=pc+EXTRACT_INT(pc); + num_locals=EXTRACT_UCHAR(addr-1); + +#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)); +#endif + + clear_svalues(sp, num_locals - args); + sp += num_locals - args; + + x=eval_instruction(addr); + 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") +{ + int x,num_locals; + char *addr; + int args=sp - *--mark_sp; + + fast_check_threads_etc(6); + + addr=pc+EXTRACT_INT(pc); + num_locals=EXTRACT_UCHAR(addr-1); + + +#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)); +#endif + + if(sp-args != fp->locals) + { + assign_svalues(fp->locals, sp-args, args, BIT_MIXED); + pop_n_elems(sp - (fp->locals + args)); + } + + clear_svalues(sp, num_locals - args); + sp += num_locals - args; + +#ifdef PIKE_DEBUG + if(sp != fp->locals + fp->num_locals) + fatal("Sp whacked!\n"); +#endif + + pc=addr; +} +BREAK diff --git a/src/language.yacc b/src/language.yacc index b20a0652f842bff25b92da318d0c329c131e0493..95083e795aacf870408229794d3f7d7f2820b74d 100644 --- a/src/language.yacc +++ b/src/language.yacc @@ -33,6 +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_LEXICAL_LOCAL F_LEXICAL_LOCAL_LVALUE @@ -192,7 +193,7 @@ /* This is the grammar definition of Pike. */ #include "global.h" -RCSID("$Id: language.yacc,v 1.180 2000/04/20 02:41:45 hubbe Exp $"); +RCSID("$Id: language.yacc,v 1.181 2000/04/25 09:32:46 hubbe Exp $"); #ifdef HAVE_MEMORY_H #include <memory.h> #endif @@ -710,13 +711,17 @@ def: modifiers type_or_error optional_stars F_IDENTIFIER push_compiler_frame0 free_string(s); } - if(compiler_pass==1) +/* if(compiler_pass==1) */ { - $<number>5=define_function(check_node_hash($4)->u.sval.u.string, - check_node_hash($<n>$)->u.sval.u.string, - $1 & (~ID_EXTERN), - IDENTIFIER_PIKE_FUNCTION, - 0); + /* FIXME: + * set current_function_number for local functions as well + */ + compiler_frame->current_function_number= + define_function(check_node_hash($4)->u.sval.u.string, + check_node_hash($<n>$)->u.sval.u.string, + $1 & (~ID_EXTERN), + IDENTIFIER_PIKE_FUNCTION, + 0); } } block_or_semi @@ -778,14 +783,16 @@ def: modifiers type_or_error optional_stars F_IDENTIFIER push_compiler_frame0 lex.current_file = save_file; #endif /* PIKE_DEBUG */ - f=dooptcode(check_node_hash($4)->u.sval.u.string, check_node_hash($10), - check_node_hash($<n>9)->u.sval.u.string, $1); + f=dooptcode(check_node_hash($4)->u.sval.u.string, + check_node_hash($10), + check_node_hash($<n>9)->u.sval.u.string, + $1); #ifdef PIKE_DEBUG if(recoveries && sp-evaluator_stack < recoveries->sp) fatal("Stack error (underflow)\n"); - if(compiler_pass == 1 && f!=$<number>5) - fatal("define_function screwed up! %d != %d\n",f,$<number>5); + if(compiler_pass == 1 && f!=compiler_frame->current_function_number) + fatal("define_function screwed up! %d != %d\n",f,compiler_frame->current_function_number); #endif } pop_compiler_frame(); diff --git a/src/las.h b/src/las.h index b1f71a36735958c3444ce8c7b550fc2c0d2e283f..286dc591de23c80e9ece75f802dbfaee06aa1f1c 100644 --- a/src/las.h +++ b/src/las.h @@ -5,7 +5,7 @@ \*/ /* - * $Id: las.h,v 1.34 2000/04/23 02:42:01 mast Exp $ + * $Id: las.h,v 1.35 2000/04/25 09:32:46 hubbe Exp $ */ #ifndef LAS_H #define LAS_H @@ -52,6 +52,7 @@ struct compiler_frame int current_number_of_locals; int max_number_of_locals; int lexical_scope; + int current_function_number; struct local_variable variable[MAX_LOCAL]; }; diff --git a/src/lex.c b/src/lex.c index 053732ae51b2fd115a46efa3c099f0650111769b..26c1a1eb5170f84af989ca7e59a15d0b9d5d72fe 100644 --- a/src/lex.c +++ b/src/lex.c @@ -5,7 +5,7 @@ \*/ /**/ #include "global.h" -RCSID("$Id: lex.c,v 1.77 2000/04/21 00:29:48 hubbe Exp $"); +RCSID("$Id: lex.c,v 1.78 2000/04/25 09:32:46 hubbe Exp $"); #include "language.h" #include "array.h" #include "lex.h" @@ -174,7 +174,6 @@ struct keyword instr_names[]= { "mark & call", F_MARK_APPLY, I_HASARG }, { "mark, call & pop", F_MARK_APPLY_POP, I_HASARG }, { "apply and return", F_APPLY_AND_RETURN, I_HASARG }, -{ "call lfun & return", F_CALL_LFUN_AND_RETURN, I_HASARG }, { "call function", F_CALL_FUNCTION, 0 }, { "call function & return", F_CALL_FUNCTION_AND_RETURN, 0 }, }; diff --git a/src/peep.in b/src/peep.in index 2d031c9dd06f4dc7d68215f3fc62b418e5b4f808..728a010f5e077e750f35ad25e2e36ad8b0f4aa4b 100644 --- a/src/peep.in +++ b/src/peep.in @@ -1,5 +1,5 @@ // -// $Id: peep.in,v 1.28 2000/04/20 02:41:45 hubbe Exp $ +// $Id: peep.in,v 1.29 2000/04/25 09:32:46 hubbe Exp $ // NOP : @@ -276,3 +276,6 @@ CONSTANT POP_VALUE : LOCAL POP_VALUE : IDENTIFIER POP_VALUE : TRAMPOLINE POP_VALUE : + + +RECUR RETURN: TAIL_RECUR ($1a) diff --git a/src/program.c b/src/program.c index 335830241c2ceab6e9f0b6bcc0237abcb160584d..679b8a31985b338b7d58df1f08653f825c231876 100644 --- a/src/program.c +++ b/src/program.c @@ -5,7 +5,7 @@ \*/ /**/ #include "global.h" -RCSID("$Id: program.c,v 1.232 2000/04/23 03:01:26 mast Exp $"); +RCSID("$Id: program.c,v 1.233 2000/04/25 09:32:46 hubbe Exp $"); #include "program.h" #include "object.h" #include "dynamic_buffer.h" @@ -3670,6 +3670,7 @@ void push_compiler_frame(int lexical_scope) f->current_number_of_locals=0; f->max_number_of_locals=0; f->previous=compiler_frame; + f->current_function_number=-2; /* no function */ compiler_frame=f; }