Main Page | Class List | Directories | File List | Class Members | File Members

apply_low.h

Go to the documentation of this file.
00001 /*
00002 || This file is part of Pike. For copyright information see COPYRIGHT.
00003 || Pike is distributed under GPL, LGPL and MPL. See the file COPYING
00004 || for more information.
00005 || $Id: apply_low.h,v 1.28 2004/05/20 20:13:38 grubba Exp $
00006 */
00007 
00008     {
00009       struct program *p;
00010       struct reference *ref;
00011       struct pike_frame *new_frame;
00012       struct identifier *function;
00013 
00014 #if 0
00015       /* This kind of fault tolerance is braindamaged. /mast */
00016       if(fun<0)
00017       {
00018         pop_n_elems(Pike_sp-save_sp);
00019         push_undefined();
00020         return 0;
00021       }
00022 #else
00023 #ifdef PIKE_DEBUG
00024       if (fun < 0)
00025         Pike_fatal ("Invalid function offset.\n");
00026 #endif
00027 #endif
00028 
00029       check_stack(256);
00030       check_mark_stack(256);
00031 
00032 #ifdef PIKE_DEBUG
00033       {
00034         static int counter;
00035         switch(d_flag)
00036         {
00037           case 0:
00038           case 1:
00039           case 2:
00040             break;
00041           case 3:
00042             if(!((counter++ & 7)))
00043               do_debug();
00044             break;
00045           case 4:
00046           default:
00047             do_debug();
00048         }
00049       }
00050 #endif
00051 
00052       p=o->prog;
00053       if(!p)
00054         PIKE_ERROR("destructed object->function",
00055               "Cannot call functions in destructed objects.\n", Pike_sp, args);
00056 
00057       if(!(p->flags & PROGRAM_PASS_1_DONE) || (p->flags & PROGRAM_AVOID_CHECK))
00058         PIKE_ERROR("__empty_program() -> function",
00059               "Cannot call functions in unfinished objects.\n", Pike_sp, args);
00060         
00061 
00062 #ifdef PIKE_SECURITY
00063       CHECK_DATA_SECURITY_OR_ERROR(o, SECURITY_BIT_CALL,
00064                                    ("Function call permission denied.\n"));
00065 
00066       if(!CHECK_DATA_SECURITY(o, SECURITY_BIT_NOT_SETUID))
00067         SET_CURRENT_CREDS(o->prot);
00068 #endif
00069 
00070 
00071 #ifdef PIKE_DEBUG
00072       if(fun>=(int)p->num_identifier_references)
00073       {
00074         fprintf(stderr, "Function index out of range. %ld >= %d\n",
00075                 DO_NOT_WARN((long)fun),
00076                 (int)p->num_identifier_references);
00077         fprintf(stderr,"########Program is:\n");
00078         describe(p);
00079         fprintf(stderr,"########Object is:\n");
00080         describe(o);
00081         Pike_fatal("Function index out of range.\n");
00082       }
00083 #endif
00084 
00085       ref = p->identifier_references + fun;
00086 #ifdef PIKE_DEBUG
00087       if(ref->inherit_offset>=p->num_inherits)
00088         Pike_fatal("Inherit offset out of range in program.\n");
00089 #endif
00090 
00091       /* init a new evaluation pike_frame */
00092       new_frame=alloc_pike_frame();
00093 #ifdef PROFILING
00094       new_frame->children_base = Pike_interpreter.accounted_time;
00095       new_frame->start_time = get_cpu_time() - Pike_interpreter.unlocked_time;
00096 
00097       /* This is mostly for profiling, but
00098        * could also be used to find out the name of a function
00099        * in a destructed object. -hubbe
00100        *
00101        * Since it not used for anything but profiling yet, I will
00102        * put it here until someone needs it. -Hubbe
00103        */
00104       new_frame->ident = ref->identifier_offset;
00105       DO_IF_PROFILING_DEBUG({
00106           fprintf(stderr, "%p{: Push at %" PRINT_CPU_TIME
00107                   " %" PRINT_CPU_TIME "\n",
00108                   Pike_interpreter.thread_state, new_frame->start_time,
00109                   new_frame->children_base);
00110         });
00111 #endif
00112       debug_malloc_touch(new_frame);
00113 
00114       new_frame->next = Pike_fp;
00115       new_frame->current_object = o;
00116       new_frame->context = p->inherits[ ref->inherit_offset ];
00117 
00118       function = new_frame->context.prog->identifiers + ref->identifier_offset;
00119       new_frame->fun = DO_NOT_WARN((unsigned INT16)fun);
00120 
00121       
00122 #ifdef PIKE_DEBUG
00123         if(Pike_interpreter.trace_level > 9)
00124         {
00125           fprintf(stderr,"-- ref: inoff=%d idoff=%d flags=%d\n",
00126                   ref->inherit_offset,
00127                   ref->identifier_offset,
00128                   ref->id_flags);
00129 
00130           fprintf(stderr,"-- context: prog->id=%d inlev=%d idlev=%d pi=%d po=%d so=%ld name=%s\n",
00131                   new_frame->context.prog->id,
00132                   new_frame->context.inherit_level,
00133                   new_frame->context.identifier_level,
00134                   new_frame->context.parent_identifier,
00135                   new_frame->context.parent_offset,
00136                   DO_NOT_WARN((long)new_frame->context.storage_offset),
00137                   new_frame->context.name ? new_frame->context.name->str  : "NULL");
00138           if(Pike_interpreter.trace_level>19)
00139           {
00140             describe(new_frame->context.prog);
00141           }
00142         }
00143 #endif
00144 
00145 
00146       new_frame->expendible =new_frame->locals = Pike_sp - args;
00147       new_frame->args = args;
00148       new_frame->pc = 0;
00149 #ifdef SCOPE
00150       new_frame->scope=scope;
00151 #ifdef PIKE_DEBUG
00152       if(new_frame->fun == scope->fun)
00153       {
00154         Pike_fatal("Que? A function cannot be parented by itself!\n");
00155       }
00156 #endif
00157 #else
00158       new_frame->scope=0;
00159 #endif
00160       new_frame->save_sp=save_sp;
00161       
00162       add_ref(new_frame->current_object);
00163       add_ref(new_frame->context.prog);
00164       if(new_frame->context.parent) add_ref(new_frame->context.parent);
00165 #ifdef SCOPE
00166       if(new_frame->scope) add_ref(new_frame->scope);
00167 #endif
00168 
00169       if(Pike_interpreter.trace_level)
00170       {
00171         dynamic_buffer save_buf;
00172         char buf[50];
00173 
00174         init_buf(&save_buf);
00175         sprintf(buf, "%lx->", DO_NOT_WARN((long) PTR_TO_INT (o)));
00176         my_strcat(buf);
00177         if (function->name->size_shift)
00178           my_strcat ("[widestring function name]");
00179         else
00180           my_strcat(function->name->str);
00181         do_trace_call(args, &save_buf);
00182       }
00183 
00184 #ifdef PIKE_DEBUG      
00185       if (Pike_fp && (new_frame->locals < Pike_fp->locals)) {
00186         fatal("New locals below old locals: %p < %p\n",
00187               new_frame->locals, Pike_fp->locals);
00188       }
00189 #endif /* PIKE_DEBUG */
00190 
00191       Pike_fp = new_frame;
00192       
00193 #ifdef PROFILING
00194       function->num_calls++;
00195 #endif
00196   
00197       if(function->func.offset == -1) {
00198         new_frame->num_args = args;
00199         generic_error(NULL, Pike_sp, args,
00200                       "Calling undefined function.\n");
00201       }
00202       
00203 #ifdef PROFILING
00204       new_frame->self_time_base=function->total_time;
00205 #endif
00206 
00207       switch(function->identifier_flags & IDENTIFIER_TYPE_MASK)
00208       {
00209       case IDENTIFIER_C_FUNCTION:
00210         debug_malloc_touch(Pike_fp);
00211         Pike_fp->num_args=args;
00212         new_frame->current_storage = o->storage+new_frame->context.storage_offset;
00213         new_frame->num_locals=args;
00214         check_threads_etc();
00215         (*function->func.c_fun)(args);
00216         break;
00217         
00218       case IDENTIFIER_CONSTANT:
00219       {
00220         struct svalue *s=&(Pike_fp->context.prog->
00221                            constants[function->func.offset].sval);
00222         debug_malloc_touch(Pike_fp);
00223         if(s->type == T_PROGRAM)
00224         {
00225           struct object *tmp;
00226           check_threads_etc();
00227           Pike_fp->num_args=args;
00228           tmp=parent_clone_object(s->u.program,
00229                                   o,
00230                                   fun,
00231                                   args);
00232           push_object(tmp);
00233           break;
00234         }
00235         /* Fall through */
00236       }
00237 
00238       case IDENTIFIER_VARIABLE:
00239       {
00240         /* FIXME:
00241          * Use new-style tail-recursion instead
00242          */
00243         debug_malloc_touch(Pike_fp);
00244         debug_malloc_touch(o);
00245         if(Pike_sp-save_sp-args<=0)
00246         {
00247           /* Create an extra svalue for tail recursion style call */
00248           Pike_sp++;
00249           MEMMOVE(Pike_sp-args,Pike_sp-args-1,sizeof(struct svalue)*args);
00250 #ifdef DEBUG_MALLOC
00251           if (args) {
00252             int i;
00253             /* Note: touch the dead svalue too. */
00254             for (i=args+2; i > 0; i--) {
00255               dmalloc_touch_svalue(Pike_sp-i);
00256             }
00257           }
00258 #endif /* DEBUG_MALLOC */             
00259           Pike_sp[-args-1].type=T_INT;
00260         }else{
00261           free_svalue(Pike_sp-args-1);
00262           Pike_sp[-args-1].type=T_INT;
00263         }
00264         low_object_index_no_free(Pike_sp-args-1,o,fun);
00265 
00266         /* No profiling code for calling variables - Hubbe */
00267         POP_PIKE_FRAME();
00268 
00269         if(Pike_sp-save_sp-args > (args<<2) + 32)
00270         {
00271           /* The test above assures these two areas
00272            * are not overlapping
00273            */
00274           assign_svalues(save_sp, Pike_sp-args, args, BIT_MIXED);
00275           pop_n_elems(Pike_sp-save_sp-args);
00276         }
00277         arg1=(void *)(Pike_sp-args-1);
00278         goto apply_svalue;
00279       }
00280 
00281       case IDENTIFIER_PIKE_FUNCTION:
00282       {
00283         int num_args;
00284         int num_locals;
00285         PIKE_OPCODE_T *pc;
00286         fast_check_threads_etc(6);
00287 
00288 #ifdef PIKE_DEBUG
00289         if (Pike_in_gc > GC_PASS_PREPARE && Pike_in_gc < GC_PASS_FREE)
00290           Pike_fatal("Pike code called within gc.\n");
00291 #endif
00292 
00293         debug_malloc_touch(Pike_fp);
00294         pc=new_frame->context.prog->program + function->func.offset;
00295 
00296         /*
00297          * FIXME: The following stack stuff could probably
00298          *        be moved to an opcode.
00299          */
00300 
00301         num_locals = READ_INCR_BYTE(pc);
00302 
00303         if(function->identifier_flags & IDENTIFIER_SCOPE_USED)
00304           new_frame->expendible+=num_locals;
00305         
00306         num_args = READ_INCR_BYTE(pc);
00307 
00308 #ifdef PIKE_DEBUG
00309         if(num_locals < num_args)
00310           Pike_fatal("Wrong number of arguments or locals in function def.\n"
00311                 "num_locals: %d < num_args: %d\n",
00312                 num_locals, num_args);
00313 #endif
00314 
00315         
00316         if(function->identifier_flags & IDENTIFIER_VARARGS)
00317         {
00318           /* adjust arguments on stack */
00319           if(args < num_args) /* push zeros */
00320           {
00321             push_undefines(num_args-args);
00322             f_aggregate(0);
00323           }else{
00324             f_aggregate(args - num_args); /* make array */
00325           }
00326           args = num_args+1;
00327         }else{
00328           /* adjust arguments on stack */
00329           if(args < num_args) /* push zeros */
00330             push_undefines(num_args-args);
00331           else
00332             pop_n_elems(args - num_args);
00333           args=num_args;
00334         }
00335 
00336         if(num_locals > args)
00337           push_zeroes(num_locals-args);
00338 
00339         new_frame->num_locals=num_locals;
00340         new_frame->num_args=num_args;
00341         new_frame->save_mark_sp=new_frame->mark_sp_base=Pike_mark_sp;
00342         new_frame->pc = pc
00343 #ifdef ENTRY_PROLOGUE_SIZE
00344           + ENTRY_PROLOGUE_SIZE
00345 #endif /* ENTRY_PROLOGUE_SIZE */
00346           ;
00347         return 1;
00348       }
00349 
00350       default:;
00351 #ifdef PIKE_DEBUG
00352         Pike_fatal("Unknown identifier type.\n");
00353 #endif
00354       }
00355 
00356 #if 0
00357 #ifdef PIKE_DEBUG
00358       if(Pike_fp!=new_frame)
00359         Pike_fatal("Frame stack out of whack!\n");
00360 #endif
00361 #endif
00362       
00363       POP_PIKE_FRAME();
00364     }

Generated on Fri Jul 22 23:44:24 2005 for Pike by  doxygen 1.3.9.1