diff --git a/src/interpret.c b/src/interpret.c index 225e5fa49fafc7d795f0438401d93c7579d4b4d8..e71d1e38fdf03b469537b39822635ebf809f4b4e 100644 --- a/src/interpret.c +++ b/src/interpret.c @@ -5,7 +5,7 @@ \*/ /**/ #include "global.h" -RCSID("$Id: interpret.c,v 1.192 2001/04/25 21:26:45 hubbe Exp $"); +RCSID("$Id: interpret.c,v 1.193 2001/05/10 22:14:36 hubbe Exp $"); #include "interpret.h" #include "object.h" #include "program.h" @@ -765,6 +765,7 @@ struct light_frame_info struct pike_frame *saved_fp; struct svalue *expendible; struct svalue *locals; + unsigned INT16 flags; }; static void restore_light_frame_info(struct light_frame_info *info) @@ -772,6 +773,7 @@ static void restore_light_frame_info(struct light_frame_info *info) if (Pike_fp == info->saved_fp) { Pike_fp->expendible = info->expendible; Pike_fp->locals = info->locals; + Pike_fp->flags=info->flags; } } @@ -863,7 +865,7 @@ static void do_trace_call(INT32 args) #undef INIT_BLOCK -#define INIT_BLOCK(X) do { X->refs=1; X->malloced_locals=0; X->scope=0; }while(0) +#define INIT_BLOCK(X) do { X->refs=1; X->flags=0; X->scope=0; }while(0) #undef EXIT_BLOCK #define EXIT_BLOCK(X) do { \ @@ -871,7 +873,7 @@ static void do_trace_call(INT32 args) if(X->context.prog) free_program(X->context.prog); \ if(X->context.parent) free_object(X->context.parent); \ if(X->scope) free_pike_frame(X->scope); \ - if(X->malloced_locals) \ + if(X->flags & PIKE_FRAME_MALLOCED_LOCALS) \ { \ free_svalues(X->locals,X->num_locals,BIT_MIXED); \ free((char *)(X->locals)); \ @@ -882,7 +884,7 @@ static void do_trace_call(INT32 args) X->context.name=0; \ X->scope=0; \ X->current_object=0; \ - X->malloced_locals=0; \ + X->flags=0; \ X->expendible=0; \ X->locals=0; \ ) \ @@ -891,6 +893,569 @@ static void do_trace_call(INT32 args) BLOCK_ALLOC(pike_frame,128) +int low_mega_apply(enum apply_type type, INT32 args, void *arg1, void *arg2) +{ + struct object *o; + struct pike_frame *scope=0; + ptrdiff_t fun; + struct svalue *save_sp=Pike_sp-args; + int tailrecurse=-1; + + +#if defined(PIKE_DEBUG) && defined(_REENTRANT) + if(d_flag) + { + THREAD_T self = th_self(); + + CHECK_INTERPRETER_LOCK(); + + if( Pike_interpreter.thread_id && !th_equal( OBJ2THREAD(Pike_interpreter.thread_id)->id, self) ) + fatal("Current thread is wrong.\n"); + + if(thread_for_id(th_self()) != Pike_interpreter.thread_id) + fatal("thread_for_id() (or Pike_interpreter.thread_id) failed in mega_apply! " + "%p != %p\n", thread_for_id(self), Pike_interpreter.thread_id); + } +#endif + + switch(type) + { + case APPLY_STACK: + apply_stack: + if(!args) + PIKE_ERROR("`()", "Too few arguments (apply stack).\n", Pike_sp, 0); + args--; + if(Pike_sp-save_sp-args > (args<<2) + 32) + { + /* The test above assures these two areas + * are not overlapping + */ + assign_svalues(save_sp, Pike_sp-args-1, args+1, BIT_MIXED); + pop_n_elems(Pike_sp-save_sp-args-1); + } + arg1=(void *)(Pike_sp-args-1); + + case APPLY_SVALUE: + apply_svalue: + { + struct svalue *s=(struct svalue *)arg1; + switch(s->type) + { + case T_INT: + if (!s->u.integer) { + PIKE_ERROR("0", "Attempt to call the NULL-value\n", Pike_sp, args); + } else { + Pike_error("Attempt to call the value %"PRINTPIKEINT"d\n", + s->u.integer); + } + + case T_STRING: + if (s->u.string->len > 20) { + Pike_error("Attempt to call the string \"%20s\"...\n", s->u.string->str); + } else { + Pike_error("Attempt to call the string \"%s\"\n", s->u.string->str); + } + case T_MAPPING: + Pike_error("Attempt to call a mapping\n"); + default: + Pike_error("Call to non-function value type:%s.\n", + get_name_of_type(s->type)); + + case T_FUNCTION: + if(s->subtype == FUNCTION_BUILTIN) + { +#ifdef PIKE_DEBUG + struct svalue *expected_stack = Pike_sp-args; + if(t_flag>1) + { + init_buf(); + describe_svalue(s,0,0); + do_trace_call(args); + } +#endif + (*(s->u.efun->function))(args); + +#ifdef PIKE_DEBUG + if(Pike_sp != expected_stack + !s->u.efun->may_return_void) + { + if(Pike_sp < expected_stack) + fatal("Function popped too many arguments: %s\n", + s->u.efun->name->str); + if(Pike_sp>expected_stack+1) + fatal("Function left droppings on stack: %s\n", + s->u.efun->name->str); + if(Pike_sp == expected_stack && !s->u.efun->may_return_void) + fatal("Non-void function returned without return value on stack: %s %d\n", + s->u.efun->name->str,s->u.efun->may_return_void); + if(Pike_sp==expected_stack+1 && s->u.efun->may_return_void) + fatal("Void function returned with a value on the stack: %s %d\n", + s->u.efun->name->str, s->u.efun->may_return_void); + } +#endif + + break; + }else{ + o=s->u.object; + if(o->prog == pike_trampoline_program) + { + fun=((struct pike_trampoline *)(o->storage))->func; + scope=((struct pike_trampoline *)(o->storage))->frame; + o=scope->current_object; + goto apply_low_with_scope; + } + fun=s->subtype; + goto apply_low; + } + break; + + case T_ARRAY: +#ifdef PIKE_DEBUG + if(t_flag>1) + { + init_buf(); + describe_svalue(s,0,0); + do_trace_call(args); + } +#endif + apply_array(s->u.array,args); + break; + + case T_PROGRAM: +#ifdef PIKE_DEBUG + if(t_flag>1) + { + init_buf(); + describe_svalue(s,0,0); + do_trace_call(args); + } +#endif + push_object(clone_object(s->u.program,args)); + break; + + case T_OBJECT: + o=s->u.object; + if(o->prog == pike_trampoline_program) + { + fun=((struct pike_trampoline *)(o->storage))->func; + scope=((struct pike_trampoline *)(o->storage))->frame; + o=scope->current_object; + goto apply_low_with_scope; + } + fun=LFUN_CALL; + goto call_lfun; + } + break; + } + + call_lfun: +#ifdef PIKE_DEBUG + if(fun < 0 || fun >= NUM_LFUNS) + fatal("Apply lfun on illegal value!\n"); +#endif + if(!o->prog) + PIKE_ERROR("destructed object", "Apply on destructed object.\n", Pike_sp, args); + fun = FIND_LFUN(o->prog, fun); + goto apply_low; + + + case APPLY_LOW: + o = (struct object *)arg1; + fun = (ptrdiff_t)arg2; + + apply_low: + scope=0; + apply_low_with_scope: + { + struct program *p; + struct reference *ref; + struct pike_frame *new_frame; + struct identifier *function; + + if(fun<0) + { + pop_n_elems(Pike_sp-save_sp); + push_int(0); + return 0; + } + + check_stack(256); + check_mark_stack(256); + check_c_stack(8192); + + +#ifdef PIKE_DEBUG + if(d_flag>2) do_debug(); +#endif + + p=o->prog; + if(!p) + PIKE_ERROR("destructed object->function", + "Cannot call functions in destructed objects.\n", Pike_sp, args); + +#ifdef PIKE_SECURITY + CHECK_DATA_SECURITY_OR_ERROR(o, SECURITY_BIT_CALL, + ("Function call permission denied.\n")); + + if(!CHECK_DATA_SECURITY(o, SECURITY_BIT_NOT_SETUID)) + SET_CURRENT_CREDS(o->prot); +#endif + + +#ifdef PIKE_DEBUG + if(fun>=(int)p->num_identifier_references) + { + fprintf(stderr, "Function index out of range. %ld >= %d\n", + DO_NOT_WARN((long)fun), + (int)p->num_identifier_references); + fprintf(stderr,"########Program is:\n"); + describe(p); + fprintf(stderr,"########Object is:\n"); + describe(o); + fatal("Function index out of range.\n"); + } +#endif + + ref = p->identifier_references + fun; +#ifdef PIKE_DEBUG + if(ref->inherit_offset>=p->num_inherits) + fatal("Inherit offset out of range in program.\n"); +#endif + + /* init a new evaluation pike_frame */ + new_frame=alloc_pike_frame(); +#ifdef PROFILING +#ifdef HAVE_GETHRTIME + new_frame->>children_base = Pike_interpreter.accounted_time; + new_frame->start_time = gethrtime() - Pike_interpreter.time_base; +#endif +#endif + debug_malloc_touch(new_frame); + + new_frame->next = Pike_fp; + new_frame->current_object = o; + new_frame->context = p->inherits[ ref->inherit_offset ]; + + function = new_frame->context.prog->identifiers + ref->identifier_offset; + + +#ifdef PIKE_DEBUG + if(t_flag > 9) + { + fprintf(stderr,"-- ref: inoff=%d idoff=%d flags=%d\n", + ref->inherit_offset, + ref->identifier_offset, + ref->id_flags); + + fprintf(stderr,"-- context: prog->id=%d inlev=%d idlev=%d pi=%d po=%d so=%ld name=%s\n", + new_frame->context.prog->id, + new_frame->context.inherit_level, + new_frame->context.identifier_level, + new_frame->context.parent_identifier, + new_frame->context.parent_offset, + DO_NOT_WARN((long)new_frame->context.storage_offset), + new_frame->context.name ? new_frame->context.name->str : "NULL"); + if(t_flag>19) + { + describe(new_frame->context.prog); + } + } +#endif + + + new_frame->locals = Pike_sp - args; + new_frame->expendible = new_frame->locals; + new_frame->args = args; + new_frame->fun = DO_NOT_WARN((unsigned INT16)fun); + new_frame->current_storage = o->storage+new_frame->context.storage_offset; + new_frame->pc = 0; + new_frame->scope=scope; + new_frame->save_sp=save_sp; + + add_ref(new_frame->current_object); + add_ref(new_frame->context.prog); + if(new_frame->context.parent) add_ref(new_frame->context.parent); + if(new_frame->scope) add_ref(new_frame->scope); + + if(t_flag) + { + char buf[50]; + + init_buf(); + sprintf(buf, "%lx->", + DO_NOT_WARN((long)o)); + my_strcat(buf); + my_strcat(function->name->str); + do_trace_call(args); + } + + Pike_fp = new_frame; + +#ifdef PROFILING + function->num_calls++; +#endif + + if(function->func.offset == -1) + generic_error(NULL, Pike_sp, args, + "Calling undefined function.\n"); + +#ifdef PROFILING +#ifdef HAVE_GETHRTIME + new_frame->self_time_base=function->total_time; +#endif +#endif + + tailrecurse=-1; + switch(function->identifier_flags & (IDENTIFIER_FUNCTION | IDENTIFIER_CONSTANT)) + { + case IDENTIFIER_C_FUNCTION: + debug_malloc_touch(Pike_fp); + Pike_fp->num_args=args; + new_frame->num_locals=args; + check_threads_etc(); + (*function->func.c_fun)(args); + break; + + case IDENTIFIER_CONSTANT: + { + struct svalue *s=&(Pike_fp->context.prog-> + constants[function->func.offset].sval); + debug_malloc_touch(Pike_fp); + if(s->type == T_PROGRAM) + { + struct object *tmp; + check_threads_etc(); + tmp=parent_clone_object(s->u.program, + o, + fun, + args); + push_object(tmp); + break; + } + /* Fall through */ + } + + case 0: + { + /* FIXME: + * Use new-style tail-recursion instead + */ + debug_malloc_touch(Pike_fp); + debug_malloc_touch(o); + if(Pike_sp-save_sp-args<=0) + { + /* Create an extra svalue for tail recursion style call */ + Pike_sp++; + MEMMOVE(Pike_sp-args,Pike_sp-args-1,sizeof(struct svalue)*args); + Pike_sp[-args-1].type=T_INT; + }else{ + free_svalue(Pike_sp-args-1); + Pike_sp[-args-1].type=T_INT; + } + low_object_index_no_free(Pike_sp-args-1,o,fun); + tailrecurse=args+1; + break; + } + + case IDENTIFIER_PIKE_FUNCTION: + { + int num_args; + int num_locals; + unsigned char *pc; + +#ifdef PIKE_DEBUG + if (Pike_in_gc > GC_PASS_PREPARE && Pike_in_gc < GC_PASS_KILL) + fatal("Pike code called within gc.\n"); +#endif + + debug_malloc_touch(Pike_fp); + pc=new_frame->context.prog->program + function->func.offset; + + num_locals=EXTRACT_UCHAR(pc++); + num_args=EXTRACT_UCHAR(pc++); + + if(function->identifier_flags & IDENTIFIER_SCOPE_USED) + new_frame->expendible+=num_locals; + + /* adjust arguments on stack */ + if(args < num_args) /* push zeros */ + { + clear_svalues_undefined(Pike_sp, num_args-args); + Pike_sp += num_args-args; + args += num_args-args; + } + + if(function->identifier_flags & IDENTIFIER_VARARGS) + { + f_aggregate(args - num_args); /* make array */ + args = num_args+1; + }else{ + if(args > num_args) + { + /* pop excessive */ + pop_n_elems(args - num_args); + args=num_args; + } + } + + if(num_locals > args) + clear_svalues(Pike_sp, num_locals - args); + Pike_sp += num_locals - args; +#ifdef PIKE_DEBUG + if(num_locals < num_args) + fatal("Wrong number of arguments or locals in function def.\n"); +#endif + new_frame->num_locals=num_locals; + new_frame->num_args=num_args; + new_frame->save_mark_sp=Pike_mark_sp; + check_threads_etc(); + new_frame->pc=pc; + return 1; + } + } +#ifdef PROFILING +#ifdef HAVE_GETHRTIME + { + long long time_passed, time_in_children, self_time; + time_in_children= Pike_interpreter.accounted_time - Pike_fp->children_base; + time_passed = gethrtime() - Pike_interpreter.time_base - Pike_fp->start_time; + self_time=time_passed - time_in_children; + Pike_interpreter.accounted_time+=self_time; + function->total_time=Pike_fp->self_time_base + (INT32)(time_passed /1000); + function->self_time+=(INT32)( self_time /1000); + } +#endif +#endif + +#if 0 +#ifdef PIKE_DEBUG + if(Pike_fp!=new_frame) + fatal("Frame stack out of whack!\n"); +#endif +#endif + + POP_PIKE_FRAME(); + + if(tailrecurse>=0) + { + args=tailrecurse; + goto apply_stack; + } + } + } + + if(save_sp+1 < Pike_sp) + { + assign_svalue(save_sp,Pike_sp-1); + pop_n_elems(Pike_sp-save_sp-1); + + destruct_objects_to_destruct(); /* consider using a flag for immediate destruct instead... */ + } + + if(save_sp+1 > Pike_sp) + { + if(type != APPLY_SVALUE) + push_int(0); + }else{ + if(t_flag>1) trace_return_value(); + } + return 0; +} + + +void low_return(void) +{ + struct svalue *save_sp=Pike_fp->save_sp; +#ifdef PIKE_DEBUG + if(Pike_mark_sp < Pike_fp->save_mark_sp) + fatal("Popped below save_mark_sp!\n"); + if(Pike_sp<Pike_interpreter.evaluator_stack) + fatal("Stack error (also simple).\n"); +#endif + Pike_mark_sp=Pike_fp->save_mark_sp; + +#ifdef PROFILING +#ifdef HAVE_GETHRTIME + { + long long time_passed, time_in_children, self_time; + time_in_children= Pike_interpreter.accounted_time - Pike_fp->children_base; + time_passed = gethrtime() - Pike_interpreter.time_base - Pike_fp->start_time; + self_time=time_passed - time_in_children; + Pike_interpreter.accounted_time+=self_time; + function->total_time=Pike_fp->self_time_base + (INT32)(time_passed /1000); + function->self_time+=(INT32)( self_time /1000); + } +#endif +#endif + + POP_PIKE_FRAME(); + + if(save_sp+1 < Pike_sp) + { + assign_svalue(save_sp,Pike_sp-1); + pop_n_elems(Pike_sp-save_sp-1); + + destruct_objects_to_destruct(); /* consider using a flag for immediate destruct instead... */ + } + + if(save_sp+1 > Pike_sp) + { + push_int(0); + }else{ + if(t_flag>1) trace_return_value(); + } +} + +void unlink_previous_frame(void) +{ + struct pike_frame *current, *prev; + struct svalue *target, **smsp; + int freespace; + current=Pike_interpreter.frame_pointer; + prev=Pike_interpreter.frame_pointer=current->next; + + target=prev->save_sp; + smsp=prev->save_mark_sp; + current->flags=prev->flags; + POP_PIKE_FRAME(); + + prev=current->next=Pike_interpreter.frame_pointer; + Pike_interpreter.frame_pointer=current; + + current->save_sp=target; + current->save_mark_sp=smsp; + +#if 1 + /* Move svalues down */ + freespace=fp->locals - target; + if(freespace > ((Pike_sp - fp->locals)<<2) + 32) + { + assign_svalues(target, + fp->locals, + Pike_sp - fp->locals, + BIT_MIXED); + + fp->locals-=freespace; + fp->expendible-=freespace; + } + + /* Move pointers down */ + freespace=fp->mark_sp_base - smsp; + if(freespace > ((Pike_mark_sp - fp->mark_sp_base)<<2)+32) + { + MEMMOVE(smsp, + fp->save_mark_sp, + sizeof(struct svalue **)*(Pike_mark_sp - fp->mark_sp_base)); + fp->mark_sp_base-=freespace; + } +#endif +} + +void gdb_stop_here(void) +{ + ; +} + + #ifdef PIKE_SECURITY /* Magic trick */ @@ -900,8 +1465,17 @@ static #define mega_apply2 mega_apply #endif +void mega_apply2(enum apply_type type, INT32 args, void *arg1, void *arg2) +{ + if(low_mega_apply(type, args, arg1, arg2)) + { + eval_instruction(Pike_fp->pc); + low_return(); + } +} -PMOD_EXPORT void mega_apply2(enum apply_type type, INT32 args, void *arg1, void *arg2) +#if 0 /* old mega_apply */ +void mega_apply2(enum apply_type type, INT32 args, void *arg1, void *arg2) { struct object *o; struct pike_frame *scope=0; @@ -909,24 +1483,6 @@ PMOD_EXPORT void mega_apply2(enum apply_type type, INT32 args, void *arg1, void ptrdiff_t fun; struct svalue *save_sp=Pike_sp-args; -#ifdef PROFILING -#ifdef HAVE_GETHRTIME - long long children_base = Pike_interpreter.accounted_time; - long long start_time = gethrtime() - Pike_interpreter.time_base; - unsigned INT32 self_time_base; -#if 0 -#ifdef PIKE_DEBUG - if(start_time < 0) - { - fatal("gethrtime() shrunk\n start_time=%ld\n gethrtime()=%ld\n Pike_interpreter.time_base=%ld\n", - (long)(start_time/100000), - (long)(gethrtime()/100000), - (long)(Pike_interpreter.time_base/100000)); - } -#endif -#endif -#endif -#endif #if defined(PIKE_DEBUG) && defined(_REENTRANT) if(d_flag) @@ -1092,6 +1648,13 @@ PMOD_EXPORT void mega_apply2(enum apply_type type, INT32 args, void *arg1, void scope=0; apply_low_with_scope: { +#ifdef PROFILING +#ifdef HAVE_GETHRTIME + long long children_base = Pike_interpreter.accounted_time; + long long start_time = gethrtime() - Pike_interpreter.time_base; + unsigned INT32 self_time_base; +#endif +#endif struct program *p; struct reference *ref; struct pike_frame *new_frame; @@ -1323,26 +1886,21 @@ PMOD_EXPORT void mega_apply2(enum apply_type type, INT32 args, void *arg1, void #endif new_frame->num_locals=num_locals; new_frame->num_args=num_args; - + new_frame->save_mark_sp=Pike_mark_sp; + new_frame->mark_sp_base=Pike_mark_sp; check_threads_etc(); - { - struct svalue **save_mark_sp=Pike_mark_sp; - tailrecurse=eval_instruction(pc); - EVAL_INSTR_RET_CHECK(tailrecurse); - Pike_mark_sp=save_mark_sp; -#ifdef PIKE_DEBUG - if(Pike_mark_sp < save_mark_sp) - fatal("Popped below save_mark_sp!\n"); -#endif - } + tailrecurse=eval_instruction(pc); + EVAL_INSTR_RET_CHECK(tailrecurse); + Pike_mark_sp=new_frame->save_mark_sp; #ifdef PIKE_DEBUG + if(Pike_mark_sp < save_mark_sp) + fatal("Popped below save_mark_sp!\n"); if(Pike_sp<Pike_interpreter.evaluator_stack) fatal("Stack error (also simple).\n"); #endif break; } - } #ifdef PROFILING #ifdef HAVE_GETHRTIME @@ -1352,41 +1910,12 @@ PMOD_EXPORT void mega_apply2(enum apply_type type, INT32 args, void *arg1, void time_passed = gethrtime() - Pike_interpreter.time_base - start_time; self_time=time_passed - time_in_children; Pike_interpreter.accounted_time+=self_time; -#if 0 -#ifdef PIKE_DEBUG - if(self_time < 0 || children_base <0 || Pike_interpreter.accounted_time <0) - fatal("Time is negative\n self_time=%ld\n time_passed=%ld\n time_in_children=%ld\n children_base=%ld\n Pike_interpreter.accounted_time=%ld!\n Pike_interpreter.time_base=%ld\n start_time=%ld\n", - (long)(self_time/100000), - (long)(time_passed/100000), - (long)(time_in_children/100000), - (long)(children_base/100000), - (long)(Pike_interpreter.accounted_time/100000), - (long)(Pike_interpreter.time_base/100000), - (long)(start_time/100000) - ); -#endif -#endif function->total_time=self_time_base + (INT32)(time_passed /1000); function->self_time+=(INT32)( self_time /1000); } #endif #endif -#if 0 - if(Pike_sp - new_frame->locals > 1) - { - pop_n_elems(Pike_sp - new_frame->locals -1); - }else if(Pike_sp - new_frame->locals < 1){ -#ifdef PIKE_DEBUG - if(Pike_sp - new_frame->locals<0) fatal("Frame underflow.\n"); -#endif - Pike_sp->u.integer = 0; - Pike_sp->subtype=NUMBER_NUMBER; - Pike_sp->type = T_INT; - Pike_sp++; - } -#endif - #ifdef PIKE_DEBUG if(Pike_fp!=new_frame) fatal("Frame stack out of whack!\n"); @@ -1399,7 +1928,6 @@ PMOD_EXPORT void mega_apply2(enum apply_type type, INT32 args, void *arg1, void args=tailrecurse; goto apply_stack; } - } } @@ -1419,6 +1947,7 @@ PMOD_EXPORT void mega_apply2(enum apply_type type, INT32 args, void *arg1, void if(t_flag>1) trace_return_value(); } } +#endif /* OLD mega_apply */ #ifdef PIKE_SECURITY static void restore_creds(struct object *creds) @@ -1449,6 +1978,8 @@ static int o_catch(unsigned char *pc) { JMP_BUF tmp; struct svalue *expendible=Pike_fp->expendible; + int flags=Pike_fp->flags; + debug_malloc_touch(Pike_fp); if(SETJMP(tmp)) { @@ -1457,11 +1988,15 @@ static int o_catch(unsigned char *pc) Pike_sp++; UNSETJMP(tmp); Pike_fp->expendible=expendible; + Pike_fp->flags=flags; return 0; }else{ struct svalue **save_mark_sp=Pike_mark_sp; int x; Pike_fp->expendible=Pike_fp->locals + Pike_fp->num_locals; + + Pike_fp->flags&=~PIKE_FRAME_RETURN_INTERNAL; + x=eval_instruction(pc); #ifdef PIKE_DEBUG if(Pike_mark_sp < save_mark_sp) @@ -1469,6 +2004,7 @@ static int o_catch(unsigned char *pc) #endif Pike_mark_sp=save_mark_sp; Pike_fp->expendible=expendible; + Pike_fp->flags=flags; if(x>=0) mega_apply(APPLY_STACK, x, 0,0); UNSETJMP(tmp); return x == -2 ? 2 : 1; diff --git a/src/interpret.h b/src/interpret.h index 084b3dcc80fde5d197d59a5820071c1d8ec8b227..1d5a02f0d482bfda604e9c055e8560835863043b 100644 --- a/src/interpret.h +++ b/src/interpret.h @@ -5,7 +5,7 @@ \*/ /* - * $Id: interpret.h,v 1.80 2001/04/28 19:39:20 mast Exp $ + * $Id: interpret.h,v 1.81 2001/05/10 22:14:37 hubbe Exp $ */ #ifndef INTERPRET_H #define INTERPRET_H @@ -55,17 +55,39 @@ struct pike_frame unsigned INT16 fun; INT16 num_locals; INT16 num_args; - INT16 malloced_locals; + unsigned INT16 flags; struct pike_frame *next; struct pike_frame *scope; unsigned char *pc; struct svalue *locals; + + /* This is <= locals, and this is where the + * return value should go. + */ + struct svalue *save_sp; + + /* This tells us the current level of + * svalues on the stack that can be discarded once the + * current function is done with them + */ struct svalue *expendible; + struct svalue **save_mark_sp; + struct svalue **mark_sp_base; struct object *current_object; + +#if defined(PROFILING) && defined(HAVE_GETHRTIME) + long long children_base; + long long start_time; + INT32 self_time_base; +#endif struct inherit context; char *current_storage; }; +#define PIKE_FRAME_RETURN_INTERNAL 1 +#define PIKE_FRAME_RETURN_POP 2 +#define PIKE_FRAME_MALLOCED_LOCALS 0x8000 + struct external_variable_context { struct object *o; @@ -196,7 +218,7 @@ PMOD_EXPORT const char *Pike_check_c_stack_errmsg; Pike_fp->num_locals); \ assign_svalues_no_free(s,Pike_fp->locals,Pike_fp->num_locals,BIT_MIXED); \ Pike_fp->locals=s; \ - Pike_fp->malloced_locals=1; \ + Pike_fp->flags|=PIKE_FRAME_MALLOCED_LOCALS; \ }else{ \ Pike_fp->locals=0; \ } \ @@ -265,7 +287,10 @@ BLOCK_ALLOC(pike_frame,128) PMOD_EXPORT void find_external_context(struct external_variable_context *loc, int arg2); -PMOD_EXPORT void mega_apply(enum apply_type type, INT32 args, void *arg1, void *arg2); +int low_mega_apply(enum apply_type type, INT32 args, void *arg1, void *arg2); +void low_return(void); +void unlink_previous_frame(void); +void mega_apply(enum apply_type type, INT32 args, void *arg1, void *arg2); PMOD_EXPORT void f_call_function(INT32 args); PMOD_EXPORT void call_handle_error(void); PMOD_EXPORT int apply_low_safe_and_stupid(struct object *o, INT32 offset); diff --git a/src/interpret_functions.h b/src/interpret_functions.h index 86d472db670a9223040007d82a24c7346db8f325..3656e6490161b6b41ced6d0fe64d654fcd902938 100644 --- a/src/interpret_functions.h +++ b/src/interpret_functions.h @@ -1,5 +1,5 @@ /* - * $Id: interpret_functions.h,v 1.51 2001/04/25 21:26:46 hubbe Exp $ + * $Id: interpret_functions.h,v 1.52 2001/05/10 22:14:37 hubbe Exp $ * * Opcode definitions for the interpreter. */ @@ -903,7 +903,8 @@ BREAK; CASE(F_CATCH); switch (o_catch(pc+sizeof(INT32))) { case 1: - return -1; /* There was a return inside the evaluated code */ + /* There was a return inside the evaluated code */ + goto do_dumb_return; case 2: pc = Pike_fp->pc; break; @@ -1052,47 +1053,6 @@ BREAK; break; } - CASE(F_APPLY_AND_RETURN); - { - INT32 args = DO_NOT_WARN(Pike_sp - *--Pike_mark_sp); -/* fprintf(stderr,"%p >= %p\n",Pike_fp->expendible,Pike_sp-args); */ - if(Pike_fp->expendible >= Pike_sp-args) - { -/* fprintf(stderr,"NOT EXPENDIBLE!\n"); */ - MEMMOVE(Pike_sp-args+1,Pike_sp-args,args*sizeof(struct svalue)); - Pike_sp++; - Pike_sp[-args-1].type=PIKE_T_INT; - } - /* We sabotage the stack here */ - assign_svalue(Pike_sp-args-1,&Pike_fp->context.prog->constants[GET_ARG()].sval); - return args+1; - } - -OPCODE1(F_CALL_LFUN_AND_RETURN,"call lfun & return") -{ - INT32 args = DO_NOT_WARN(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=arg1+Pike_fp->context.identifier_level; -#ifdef PIKE_DEBUG - 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; -} -BREAK CASE(F_RETURN_LOCAL); instr=GET_ARG(); @@ -1112,7 +1072,7 @@ BREAK push_svalue(Pike_fp->locals+instr); } print_return_value(); - return -1; + goto do_dumb_return; CASE(F_RETURN_IF_TRUE); if(!IS_ZERO(Pike_sp-1)) goto do_return; @@ -1138,6 +1098,17 @@ BREAK /* fall through */ CASE(F_DUMB_RETURN); + do_dumb_return: + if(Pike_fp -> flags & PIKE_FRAME_RETURN_INTERNAL) + { + int f=Pike_fp->flags; + gdb_stop_here(); + low_return(); + if(f & PIKE_FRAME_RETURN_POP) + pop_stack(); + pc=Pike_fp->pc; + break; + } return -1; OPCODE0(F_NEGATE, "unary minus") @@ -1533,71 +1504,178 @@ OPCODE1(F_SSCANF, "sscanf") BREAK; OPCODE1(F_CALL_LFUN,"call lfun") +#if 0 apply_low(Pike_fp->current_object, arg1+Pike_fp->context.identifier_level, DO_NOT_WARN(Pike_sp - *--Pike_mark_sp)); +#else + if(low_mega_apply(APPLY_LOW, + DO_NOT_WARN(Pike_sp - *--Pike_mark_sp), + Pike_fp->current_object, + (void *)(arg1+Pike_fp->context.identifier_level))) + { + Pike_fp->next->pc=pc; + gdb_stop_here(); + Pike_fp->flags |= PIKE_FRAME_RETURN_INTERNAL; + pc=Pike_fp->pc; + } +#endif BREAK; OPCODE1(F_CALL_LFUN_AND_POP,"call lfun & pop") +#if 1 apply_low(Pike_fp->current_object, - arg1+Pike_fp->context.identifier_level, - DO_NOT_WARN(Pike_sp - *--Pike_mark_sp)); + arg1+Pike_fp->context.identifier_level, + DO_NOT_WARN(Pike_sp - *--Pike_mark_sp)); pop_stack(); +#else + if(low_mega_apply(APPLY_LOW, + DO_NOT_WARN(Pike_sp - *--Pike_mark_sp), + Pike_fp->current_object, + (void *)(arg1+Pike_fp->context.identifier_level))) + { + Pike_fp->next->pc=pc; + gdb_stop_here(); + Pike_fp->flags |= PIKE_FRAME_RETURN_INTERNAL | PIKE_FRAME_RETURN_POP; + pc=Pike_fp->pc; + }else{ + pop_stack(); + } +#endif BREAK; OPCODE1(F_MARK_APPLY,"mark apply") - strict_apply_svalue(&((Pike_fp->context.prog->constants + arg1)->sval), 0); + if(low_mega_apply(APPLY_SVALUE, + 0, + &((Pike_fp->context.prog->constants + arg1)->sval),0)) + { + Pike_fp->next->pc=pc; + gdb_stop_here(); + Pike_fp->flags |= PIKE_FRAME_RETURN_INTERNAL; + pc=Pike_fp->pc; + } BREAK; OPCODE1(F_MARK_APPLY_POP,"mark, apply & pop") - strict_apply_svalue(&((Pike_fp->context.prog->constants + arg1)->sval), 0); - pop_stack(); + if(low_mega_apply(APPLY_SVALUE, + 0, + &((Pike_fp->context.prog->constants + arg1)->sval),0)) + { + Pike_fp->next->pc=pc; + gdb_stop_here(); + Pike_fp->flags |= PIKE_FRAME_RETURN_INTERNAL | PIKE_FRAME_RETURN_POP; + pc=Pike_fp->pc; + }else{ + pop_stack(); + } BREAK; - CASE(F_APPLY); - strict_apply_svalue(&((Pike_fp->context.prog->constants + GET_ARG())->sval), - DO_NOT_WARN(Pike_sp - *--Pike_mark_sp )); - break; +OPCODE1(F_APPLY,"apply") + if(low_mega_apply(APPLY_SVALUE, + DO_NOT_WARN(Pike_sp - *--Pike_mark_sp ), + &((Pike_fp->context.prog->constants + arg1)->sval),0)) + { + Pike_fp->next->pc=pc; + gdb_stop_here(); + Pike_fp->flags |= PIKE_FRAME_RETURN_INTERNAL; + pc=Pike_fp->pc; + } +BREAK; - CASE(F_APPLY_AND_POP); - strict_apply_svalue(&((Pike_fp->context.prog->constants + GET_ARG())->sval), - DO_NOT_WARN(Pike_sp - *--Pike_mark_sp )); - pop_stack(); - break; -OPCODE0(F_CALL_FUNCTION, "call function") - mega_apply(APPLY_STACK, - DO_NOT_WARN(Pike_sp - *--Pike_mark_sp), - 0,0); +OPCODE1(F_APPLY_AND_POP,"apply") + if(low_mega_apply(APPLY_SVALUE, + DO_NOT_WARN(Pike_sp - *--Pike_mark_sp ), + &((Pike_fp->context.prog->constants + arg1)->sval),0)) + { + Pike_fp->next->pc=pc; + gdb_stop_here(); + Pike_fp->flags |= PIKE_FRAME_RETURN_INTERNAL | PIKE_FRAME_RETURN_POP; + pc=Pike_fp->pc; + }else{ + pop_stack(); + } +BREAK; + + +OPCODE0(F_CALL_FUNCTION,"call function") + if(low_mega_apply(APPLY_STACK, + DO_NOT_WARN(Pike_sp - *--Pike_mark_sp ), + 0,0)) + { + Pike_fp->next->pc=pc; + gdb_stop_here(); + Pike_fp->flags |= PIKE_FRAME_RETURN_INTERNAL; + pc=Pike_fp->pc; + } BREAK; -OPCODE0(F_CALL_FUNCTION_AND_POP, "call function & pop") - mega_apply(APPLY_STACK, - DO_NOT_WARN(Pike_sp - *--Pike_mark_sp), - 0,0); - pop_stack(); + +OPCODE0(F_CALL_FUNCTION_AND_POP,"call function & pop") + if(low_mega_apply(APPLY_STACK, + DO_NOT_WARN(Pike_sp - *--Pike_mark_sp ), + 0,0)) + { + Pike_fp->next->pc=pc; + gdb_stop_here(); + Pike_fp->flags |= PIKE_FRAME_RETURN_INTERNAL | PIKE_FRAME_RETURN_POP; + pc=Pike_fp->pc; + }else{ + pop_stack(); + } BREAK; +OPCODE1(F_APPLY_AND_RETURN,"apply & return") +{ + if(low_mega_apply(APPLY_SVALUE, + DO_NOT_WARN(Pike_sp - *--Pike_mark_sp ), + &((Pike_fp->context.prog->constants + arg1)->sval),0)) + { +#ifdef PIKE_DEBUG + Pike_fp->next->pc=0; +#endif + pc=Pike_fp->pc; + unlink_previous_frame(); + }else{ + goto do_dumb_return; + } +} +BREAK; + +OPCODE1(F_CALL_LFUN_AND_RETURN,"call lfun & return") +{ + if(low_mega_apply(APPLY_LOW, + DO_NOT_WARN(Pike_sp - *--Pike_mark_sp), + Pike_fp->current_object, + (void *)(arg1+Pike_fp->context.identifier_level))) + { +#ifdef PIKE_DEBUG + Pike_fp->next->pc=0; +#endif + gdb_stop_here(); + pc=Pike_fp->pc; + unlink_previous_frame(); + }else{ + goto do_dumb_return; + } +} +BREAK + OPCODE0(F_CALL_FUNCTION_AND_RETURN, "call function & return") { - INT32 args = DO_NOT_WARN(Pike_sp - *--Pike_mark_sp); - if(!args) - PIKE_ERROR("`()", "Too few arguments (call&return).\n", Pike_sp, 0); - switch(Pike_sp[-args].type) + if(low_mega_apply(APPLY_STACK, + DO_NOT_WARN(Pike_sp - *--Pike_mark_sp ), + 0,0)) { - case PIKE_T_INT: - if (!Pike_sp[-args].u.integer) { - PIKE_ERROR("`()", "Attempt to call the NULL-value\n", - Pike_sp, args); - } - case PIKE_T_STRING: - case PIKE_T_FLOAT: - case PIKE_T_MAPPING: - case PIKE_T_MULTISET: - PIKE_ERROR("`()", "Attempt to call a non-function value.\n", - Pike_sp, args); +#ifdef PIKE_DEBUG + Pike_fp->next->pc=0; +#endif + gdb_stop_here(); + pc=Pike_fp->pc; + unlink_previous_frame(); + }else{ + goto do_dumb_return; } - return args; } BREAK; @@ -1621,9 +1699,58 @@ OPCODE1_JUMP(F_COND_RECUR,"recur if not overloaded") /* FALL THROUGH */ /* Assume that the number of arguments is correct */ +/* FIXME: Use new recursion stuff */ OPCODE0_TAILJUMP(F_RECUR,"recur") OPCODE0_TAILJUMP(F_RECUR_AND_POP,"recur & pop") { +#if 1 + int opcode = instr; + char *addr; + struct pike_frame *new_frame; + + fast_check_threads_etc(6); + check_c_stack(8192); + check_stack(256); + + new_frame=alloc_pike_frame(); + new_frame[0]=Pike_fp[0]; + + new_frame->refs=1; + new_frame->next=Pike_fp; + + new_frame->save_sp = new_frame->expendible = new_frame->locals = *--Pike_mark_sp; + new_frame->num_args = new_frame->args = DO_NOT_WARN(Pike_sp - new_frame->locals); + new_frame->save_mark_sp = Pike_mark_sp; + new_frame->mark_sp_base = Pike_mark_sp; + + addr=pc+GET_JUMP(); + new_frame->num_locals=EXTRACT_UCHAR(addr-2); + +#ifdef PIKE_DEBUG + if(new_frame->num_args != EXTRACT_UCHAR(addr-1)) + fatal("Wrong number of arguments in F_RECUR %d!=%d\n", + new_frame->num_args, EXTRACT_UCHAR(addr-1)); + + if(t_flag > 3) + fprintf(stderr,"- Allocating %d extra locals.\n", + new_frame->num_locals - new_frame->num_args); +#endif + + clear_svalues(Pike_sp, new_frame->num_locals - new_frame->num_args); + Pike_sp += new_frame->num_locals - new_frame->args; + + if(new_frame->scope) add_ref(new_frame->scope); + add_ref(new_frame->current_object); + add_ref(new_frame->context.prog); + if(new_frame->context.parent) + add_ref(new_frame->context.parent); + Pike_fp->pc=pc+sizeof(INT32); + Pike_fp=new_frame; + pc=addr; + new_frame->flags=PIKE_FRAME_RETURN_INTERNAL; + if (opcode == F_RECUR_AND_POP-F_OFFSET) + new_frame->flags|=PIKE_FRAME_RETURN_POP; +#else /* 0 */ int x, opcode = instr; INT32 num_locals, args; char *addr; @@ -1638,6 +1765,7 @@ OPCODE0_TAILJUMP(F_RECUR_AND_POP,"recur & pop") info.saved_fp = Pike_fp; info.expendible = Pike_fp->expendible; info.locals = Pike_fp->locals; + info.flags=Pike_fp->flags; SET_ONERROR(uwp, restore_light_frame_info, &info); save_sp = Pike_fp->expendible = Pike_fp->locals = *--Pike_mark_sp; @@ -1652,7 +1780,6 @@ OPCODE0_TAILJUMP(F_RECUR_AND_POP,"recur & pop") fatal("Wrong number of arguments in F_RECUR %d!=%d\n", args, EXTRACT_UCHAR(addr-1)); #endif - clear_svalues(Pike_sp, num_locals - args); Pike_sp += num_locals - args; @@ -1677,6 +1804,7 @@ OPCODE0_TAILJUMP(F_RECUR_AND_POP,"recur & pop") fatal("Stack whack in F_RECUR Pike_sp=%p, expected=%p\n",Pike_sp,save_sp+1); #endif if (opcode == F_RECUR_AND_POP-F_OFFSET) pop_stack(); +#endif /* 0 */ } BREAK diff --git a/src/lex.c b/src/lex.c index 20c84e7bf3b25ff3931b27511925e5ad3f611cc6..fa302a053b19eb7cae44d90cfc2e49885ff92e2d 100644 --- a/src/lex.c +++ b/src/lex.c @@ -5,7 +5,7 @@ \*/ /**/ #include "global.h" -RCSID("$Id: lex.c,v 1.87 2001/02/24 02:38:32 hubbe Exp $"); +RCSID("$Id: lex.c,v 1.88 2001/05/10 22:14:37 hubbe Exp $"); #include "language.h" #include "array.h" #include "lex.h" @@ -167,13 +167,10 @@ struct keyword instr_names[]= { "return if true", F_RETURN_IF_TRUE, 0 }, { "label", F_LABEL,I_HASARG }, { "align", F_ALIGN, I_HASARG }, -{ "call", F_APPLY, I_HASARG }, { "int index", F_POS_INT_INDEX, I_HASARG }, { "-int index", F_NEG_INT_INDEX, I_HASARG }, -{ "apply and pop", F_APPLY_AND_POP, I_HASARG }, { "nop", F_NOP,0 }, { "function start", F_START_FUNCTION,0 }, -{ "apply and return", F_APPLY_AND_RETURN, I_HASARG }, { "notreached!", F_NOTREACHED, 0 }, }; diff --git a/src/opcodes.h b/src/opcodes.h index 688288aa2e185e5a58be3f215376e974d8264b31..7b28a7b141e1f3a0605d7df9bf10175e5bd5c35d 100644 --- a/src/opcodes.h +++ b/src/opcodes.h @@ -5,7 +5,7 @@ \*/ /* - * $Id: opcodes.h,v 1.13 2001/02/24 02:38:33 hubbe Exp $ + * $Id: opcodes.h,v 1.14 2001/05/10 22:14:38 hubbe Exp $ */ #ifndef OPCODES_H #define OPCODES_H @@ -46,9 +46,6 @@ enum Pike_opcodes F_PREFIX2_CHARX256, F_PREFIX2_WORDX256, F_PREFIX2_24BITX256, - F_APPLY, - F_APPLY_AND_POP, - F_APPLY_AND_RETURN, F_BRANCH_AND_POP_WHEN_ZERO, F_BRANCH_AND_POP_WHEN_NON_ZERO, diff --git a/src/program.c b/src/program.c index 8af1f9481f599cc8e03b58c253ed74111f1503b4..43bda9f2c8edcaf15225f032e6281d4ed4ae0ff3 100644 --- a/src/program.c +++ b/src/program.c @@ -5,7 +5,7 @@ \*/ /**/ #include "global.h" -RCSID("$Id: program.c,v 1.319 2001/05/05 21:00:17 grubba Exp $"); +RCSID("$Id: program.c,v 1.320 2001/05/10 22:14:38 hubbe Exp $"); #include "program.h" #include "object.h" #include "dynamic_buffer.h" @@ -4238,12 +4238,13 @@ static void exit_trampoline(struct object *o) static void gc_check_frame(struct pike_frame *f) { if(!f) return; - if(!debug_gc_check(f,PIKE_T_UNKNOWN,f) && f->malloced_locals) + if(!debug_gc_check(f,PIKE_T_UNKNOWN,f) && (f->flags & PIKE_FRAME_MALLOCED_LOCALS)) { if(f->current_object) gc_check(f->current_object); if(f->context.prog) gc_check(f->context.prog); if(f->context.parent) gc_check(f->context.parent); - if(f->malloced_locals)gc_check_svalues(f->locals,f->num_locals); + if(f->flags & PIKE_FRAME_MALLOCED_LOCALS) + gc_check_svalues(f->locals,f->num_locals); if(f->scope) gc_check_frame(f->scope); } } @@ -4259,7 +4260,8 @@ static void gc_recurse_frame(struct pike_frame *f) if(f->current_object) gc_recurse_object(f->current_object); if(f->context.prog) gc_recurse_program(f->context.prog); if(f->context.parent) gc_recurse_object(f->context.parent); - if(f->malloced_locals)gc_recurse_svalues(f->locals,f->num_locals); + if(f->flags & PIKE_FRAME_MALLOCED_LOCALS) + gc_recurse_svalues(f->locals,f->num_locals); if(f->scope) gc_recurse_frame(f->scope); } diff --git a/src/testsuite.in b/src/testsuite.in index 3eab469fbc3352f089376583da164c29340ade49..689b3ed694495777cf7f594ac8601b02f535ed24 100644 --- a/src/testsuite.in +++ b/src/testsuite.in @@ -1,4 +1,4 @@ -test_true([["$Id: testsuite.in,v 1.406 2001/05/07 21:45:07 grubba Exp $"]]); +test_true([["$Id: testsuite.in,v 1.407 2001/05/10 22:14:38 hubbe Exp $"]]); cond([[all_constants()->_verify_internals]], [[ @@ -842,7 +842,8 @@ test_any([[string gurk="bozo"; string b(int x) { return (x?b(x-1)+gurk:""); }; r dnl this should really work... dnl test_compile_any([[void foo(int,string,...);]]) -test_eval_error([[class X { int create() { create(); } }();]]) +dnl This test doesn't run out of stack anymore, freaky +dnl test_eval_error([[class X { int create() { create(); } }();]]) test_compile_error([[ int float; ]]) test_compile_error([[ int array; ]]) test_compile_error([[ int function; ]])