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

interpret.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: interpret.h,v 1.162 2005/06/20 12:51:45 grubba Exp $
00006 */
00007 
00008 #ifndef INTERPRET_H
00009 #define INTERPRET_H
00010 
00011 #include "global.h"
00012 #include "program.h"
00013 #include "pike_error.h"
00014 #include "object.h"
00015 #include "pike_rusage.h"
00016 
00017 struct Pike_interpreter {
00018   /* Swapped variables */
00019   struct svalue *stack_pointer;
00020   struct svalue *evaluator_stack;
00021   struct svalue **mark_stack_pointer;
00022   struct svalue **mark_stack;
00023   struct pike_frame *frame_pointer;
00024   int evaluator_stack_malloced;
00025   int mark_stack_malloced;
00026   JMP_BUF *recoveries;
00027 #ifdef PIKE_THREADS
00028   struct thread_state *thread_state;
00029 #endif
00030   char *stack_top;
00031   DO_IF_SECURITY(struct object *current_creds;)
00032 
00033   int svalue_stack_margin;
00034   int c_stack_margin;
00035 
00036 #ifdef PROFILING
00037   cpu_time_t accounted_time;    
00038   cpu_time_t unlocked_time;     
00039   char *stack_bottom;
00040 #endif
00041 
00042   int trace_level;
00043 };
00044 
00045 #ifndef STRUCT_FRAME_DECLARED
00046 #define STRUCT_FRAME_DECLARED
00047 #endif
00048 struct pike_frame
00049 {
00050   INT32 refs;/* must be first */
00051   INT32 args;                   
00052   unsigned INT16 fun;           
00053   INT16 num_locals;             
00054   INT16 num_args;               
00055   unsigned INT16 flags;         
00056   INT16 ident;
00057   struct pike_frame *next;
00058   struct pike_frame *scope;
00059   PIKE_OPCODE_T *pc;            
00060   PIKE_OPCODE_T *return_addr;   
00061   struct svalue *locals;        
00066   struct svalue *save_sp;
00067 
00072   struct svalue *expendible;
00073   struct svalue **save_mark_sp;
00074   struct svalue **mark_sp_base;
00075   struct object *current_object;
00076 
00077   DO_IF_SECURITY(struct object *current_creds;)
00078 #if defined(PROFILING)
00079   cpu_time_t children_base;     
00080   cpu_time_t start_time;        
00081   cpu_time_t self_time_base;    /* ??? */
00082 #endif
00083   struct inherit context;
00084   char *current_storage;
00085 };
00086 
00087 #define PIKE_FRAME_RETURN_INTERNAL 1
00088 #define PIKE_FRAME_RETURN_POP 2
00089 #define PIKE_FRAME_MALLOCED_LOCALS 0x8000
00090 
00091 struct external_variable_context
00092 {
00093   struct object *o;
00094   struct inherit *inherit;
00095   int parent_identifier;
00096 };
00097 
00098 #ifdef HAVE_COMPUTED_GOTO
00099 extern PIKE_OPCODE_T *fcode_to_opcode;
00100 extern struct op_2_f {
00101   PIKE_OPCODE_T opcode;
00102   INT32 fcode;
00103 } *opcode_to_fcode;
00104 #endif /* HAVE_COMPUTED_GOTO */
00105 
00106 #ifdef PIKE_DEBUG
00107 PMOD_EXPORT extern const char msg_stack_error[];
00108 #define debug_check_stack() do{if(Pike_sp<Pike_interpreter.evaluator_stack)Pike_fatal(msg_stack_error);}while(0)
00109 #define check__positive(X,Y) if((X)<0) Pike_fatal Y
00110 #include "pike_error.h"
00111 #else
00112 #define check__positive(X,Y)
00113 #define debug_check_stack() 
00114 #endif
00115 
00116 #define low_stack_check(X) \
00117   (Pike_sp - Pike_interpreter.evaluator_stack + \
00118    Pike_interpreter.svalue_stack_margin + (X) >= Pike_stack_size)
00119 
00120 PMOD_EXPORT extern const char Pike_check_stack_errmsg[];
00121 
00122 #define check_stack(X) do { \
00123   if(low_stack_check(X)) \
00124     ((void (*)(const char *, ...))Pike_error)( \
00125                Pike_check_stack_errmsg, \
00126                PTRDIFF_T_TO_LONG(Pike_sp - Pike_interpreter.evaluator_stack), \
00127                PTRDIFF_T_TO_LONG(Pike_stack_size), \
00128                PTRDIFF_T_TO_LONG(X)); \
00129   }while(0)
00130 
00131 PMOD_EXPORT extern const char Pike_check_mark_stack_errmsg[];
00132 
00133 #define check_mark_stack(X) do {                \
00134   if(Pike_mark_sp - Pike_interpreter.mark_stack + (X) >= Pike_stack_size) \
00135     ((void (*)(const char*, ...))Pike_error)(Pike_check_mark_stack_errmsg); \
00136   }while(0)
00137 
00138 PMOD_EXPORT extern const char Pike_check_c_stack_errmsg[];
00139 
00140 #define check_c_stack(X) do {                                           \
00141   ptrdiff_t x_= ((char *)&x_) +                                         \
00142     STACK_DIRECTION * (Pike_interpreter.c_stack_margin + (X)) -         \
00143     Pike_interpreter.stack_top ;                                        \
00144   x_*=STACK_DIRECTION;                                                  \
00145   if(x_>0)                                                              \
00146     low_error(Pike_check_c_stack_errmsg);                               \
00147   }while(0)
00148 
00149 #define fatal_check_c_stack(X) do {                     \
00150     ptrdiff_t x_=                                       \
00151       ((char *)&x_) + STACK_DIRECTION * (X) - Pike_interpreter.stack_top ; \
00152     x_*=STACK_DIRECTION;                                                \
00153     if(x_>0) {                                                          \
00154       ((void (*)(const char*, ...))Pike_fatal)(Pike_check_c_stack_errmsg);      \
00155     }                                                                   \
00156   }while(0)
00157 
00158 
00159 #ifdef PIKE_DEBUG
00160 #define STACK_LEVEL_START(depth)        \
00161   do { \
00162     struct svalue *save_stack_level = (Pike_sp - (depth))
00163 
00164 #define STACK_LEVEL_DONE(depth)         \
00165     STACK_LEVEL_CHECK(depth);           \
00166   } while(0)
00167 
00168 #define STACK_LEVEL_CHECK(depth)                                        \
00169   do {                                                                  \
00170     if (Pike_sp != save_stack_level + (depth)) {                        \
00171       Pike_fatal("Unexpected stack level! "                             \
00172                  "Actual: %d, expected: %d\n",                          \
00173                  DO_NOT_WARN((int)(Pike_sp - save_stack_level)),        \
00174                  (depth));                                              \
00175     }                                                                   \
00176   } while(0)
00177 #else /* !PIKE_DEBUG */
00178 #define STACK_LEVEL_START(depth)        do {
00179 #define STACK_LEVEL_DONE(depth)         } while(0)
00180 #define STACK_LEVEL_CHECK(depth)
00181 #endif /* PIKE_DEBUG */
00182 
00183 #define pop_stack() do{ free_svalue(--Pike_sp); debug_check_stack(); }while(0)
00184 #define pop_2_elems() do { pop_stack(); pop_stack(); }while(0)
00185 
00186 #ifdef __ECL
00187 #define MAYBE_CAST_TO_LONG(X)   (X)
00188 #else /* !__ECL */
00189 #define MAYBE_CAST_TO_LONG(X)   ((long)(X))
00190 #endif /* __ECL */
00191 
00192 PMOD_EXPORT extern const char msg_pop_neg[];
00193 #define pop_n_elems(X)                                                  \
00194  do {                                                                   \
00195    ptrdiff_t x_=(X);                                                    \
00196    if(x_) {                                                             \
00197      struct svalue *_sp_;                                               \
00198      check__positive(x_, (msg_pop_neg, x_));                            \
00199      _sp_ = Pike_sp = Pike_sp - x_;                                     \
00200      debug_check_stack();                                               \
00201      free_mixed_svalues(_sp_, x_);                                      \
00202    }                                                                    \
00203  } while (0)
00204 
00205 /* This pops a number of arguments from the stack but keeps the top
00206  * element on top. Used for popping the arguments while keeping the
00207  * return value.
00208  */
00209 #define stack_unlink(X) do {                                            \
00210     ptrdiff_t x2_ = (X);                                                \
00211     if (x2_) {                                                          \
00212       struct svalue *_sp_ = --Pike_sp;                                  \
00213       free_svalue (_sp_ - x2_);                                         \
00214       move_svalue (_sp_ - x2_, _sp_);                                   \
00215       pop_n_elems (x2_ - 1);                                            \
00216     }                                                                   \
00217   }while(0)
00218 
00219 #define stack_pop_n_elems_keep_top(X) stack_unlink(X)
00220 
00221 #define stack_pop_keep_top() do {                                       \
00222     struct svalue *_sp_ = --Pike_sp;                                    \
00223     free_svalue (_sp_ - 1);                                             \
00224     move_svalue (_sp_ - 1, _sp_);                                       \
00225     debug_check_stack();                                                \
00226   } while (0)
00227 
00228 #define stack_pop_2_elems_keep_top() do {                               \
00229     struct svalue *_sp_ = Pike_sp = Pike_sp - 2;                        \
00230     free_svalue (_sp_ - 1);                                             \
00231     free_svalue (_sp_);                                                 \
00232     move_svalue (_sp_ - 1, _sp_ + 1);                                   \
00233     debug_check_stack();                                                \
00234   } while (0)
00235 
00236 #define stack_pop_to_no_free(X) move_svalue(X, --Pike_sp)
00237 
00238 #define stack_pop_to(X) do {                                            \
00239     struct svalue *_=(X);                                               \
00240     free_svalue(_);                                                     \
00241     stack_pop_to_no_free(_);                                            \
00242   }while(0)
00243 
00244 #define push_program(P) do{                                             \
00245     struct program *_=(P);                                              \
00246     struct svalue *_sp_ = Pike_sp++;                                    \
00247     debug_malloc_touch(_);                                              \
00248     _sp_->u.program=_;                                                  \
00249     _sp_++->type=PIKE_T_PROGRAM;                                        \
00250   }while(0)
00251 
00252 #define push_int(I) do{                                                 \
00253     INT_TYPE _=(I);                                                     \
00254     struct svalue *_sp_ = Pike_sp++;                                    \
00255     _sp_->u.integer=_;                                                  \
00256     _sp_->type=PIKE_T_INT;                                              \
00257     _sp_->subtype=NUMBER_NUMBER;                                        \
00258   }while(0)
00259 
00260 #define push_undefined() do{                                            \
00261     struct svalue *_sp_ = Pike_sp++;                                    \
00262     _sp_->u.integer=0;                                                  \
00263     _sp_->type=PIKE_T_INT;                                              \
00264     _sp_->subtype=NUMBER_UNDEFINED;                                     \
00265   }while(0)
00266 
00267 #define push_obj_index(I) do{                                           \
00268     int _=(I);                                                          \
00269     struct svalue *_sp_ = Pike_sp++;                                    \
00270     _sp_->u.identifier=_;                                               \
00271     _sp_->type=T_OBJ_INDEX;                                             \
00272   }while(0)
00273 
00274 #define push_mapping(M) do{                                             \
00275     struct mapping *_=(M);                                              \
00276     struct svalue *_sp_ = Pike_sp++;                                    \
00277     debug_malloc_touch(_);                                              \
00278     _sp_->u.mapping=_;                                                  \
00279     _sp_->type=PIKE_T_MAPPING;                                          \
00280   }while(0)
00281 
00282 #define push_array(A) do{                                               \
00283     struct array *_=(A);                                                \
00284     struct svalue *_sp_ = Pike_sp++;                                    \
00285     debug_malloc_touch(_);                                              \
00286     _sp_->u.array=_ ;                                                   \
00287     _sp_->type=PIKE_T_ARRAY;                                            \
00288   }while(0)
00289 
00290 #define push_empty_array() ref_push_array(&empty_array)
00291 
00292 #define push_multiset(L) do{                                            \
00293     struct multiset *_=(L);                                             \
00294     struct svalue *_sp_ = Pike_sp++;                                    \
00295     debug_malloc_touch(_);                                              \
00296     _sp_->u.multiset=_;                                                 \
00297     _sp_->type=PIKE_T_MULTISET;                                         \
00298   }while(0)
00299 
00300 #define push_string(S) do {                                             \
00301     struct pike_string *_=(S);                                          \
00302     struct svalue *_sp_ = Pike_sp++;                                    \
00303     debug_malloc_touch(_);                                              \
00304     DO_IF_DEBUG(if(_->size_shift & ~3) {                                \
00305                   Pike_fatal("Pushing string with bad shift: %d\n",     \
00306                              _->size_shift);                            \
00307                 });                                                     \
00308     _sp_->subtype=0;                                                    \
00309     _sp_->u.string=_;                                                   \
00310     _sp_->type=PIKE_T_STRING;                                           \
00311   }while(0)
00312 
00313 #define push_empty_string() ref_push_string(empty_pike_string)
00314 
00315 #define push_type_value(S) do{                                          \
00316     struct pike_type *_=(S);                                            \
00317     struct svalue *_sp_ = Pike_sp++;                                    \
00318     debug_malloc_touch(_);                                              \
00319     _sp_->u.type=_;                                                     \
00320     _sp_->type=PIKE_T_TYPE;                                             \
00321   }while(0)
00322 
00323 #define push_object(O) do {                                             \
00324     struct object *_=(O);                                               \
00325     struct svalue *_sp_ = Pike_sp++;                                    \
00326     debug_malloc_touch(_);                                              \
00327     _sp_->u.object=_;                                                   \
00328     _sp_->type=PIKE_T_OBJECT;                                           \
00329     _sp_->subtype = 0;                                                  \
00330   }while(0)
00331 
00332 #define push_object_inherit(O, INH_NUM) do {                            \
00333     struct object *_ = (O);                                             \
00334     struct svalue *_sp_ = Pike_sp++;                                    \
00335     int _inh_ = (INH_NUM);                                              \
00336     debug_malloc_touch(_);                                              \
00337     _sp_->u.object = _;                                                 \
00338     _sp_->type = PIKE_T_OBJECT;                                         \
00339     _sp_->subtype = _inh_;                                              \
00340   }while(0)
00341 
00342 #define push_float(F) do{                                               \
00343     FLOAT_TYPE _=(F);                                                   \
00344     struct svalue *_sp_ = Pike_sp++;                                    \
00345     _sp_->u.float_number=_;                                             \
00346     _sp_->type=PIKE_T_FLOAT;                                            \
00347   }while(0)
00348 
00349 #define push_text(T) do {                                               \
00350     const char *_ = (T);                                                \
00351     struct svalue *_sp_ = Pike_sp++;                                    \
00352     _sp_->subtype=0;                                                    \
00353     _sp_->u.string=make_shared_binary_string(_,strlen(_));              \
00354     debug_malloc_touch(_sp_->u.string);                                 \
00355     _sp_->type=PIKE_T_STRING;                                           \
00356   }while(0)
00357 
00358 #define push_constant_text(T) do{                                       \
00359     struct svalue *_sp_ = Pike_sp++;                                    \
00360     _sp_->subtype=0;                                                    \
00361     REF_MAKE_CONST_STRING(_sp_->u.string,T);                            \
00362     _sp_->type=PIKE_T_STRING;                                           \
00363   }while(0)
00364 
00365 #define push_constant_string_code(STR, CODE) do{                        \
00366     struct pike_string *STR;                                            \
00367     REF_MAKE_CONST_STRING_CODE (STR, CODE);                             \
00368     push_string (STR);                                                  \
00369   }while(0)
00370 
00371 #define push_function(OBJ, FUN) do {                                    \
00372     struct object *_=(OBJ);                                             \
00373     struct svalue *_sp_ = Pike_sp++;                                    \
00374     debug_malloc_touch(_);                                              \
00375     _sp_->u.object=_;                                                   \
00376     _sp_->subtype=(FUN);                                                \
00377     _sp_->type=PIKE_T_FUNCTION;                                         \
00378   } while (0)
00379 
00380 #define ref_push_program(P) do{                                         \
00381     struct program *_=(P);                                              \
00382     struct svalue *_sp_ = Pike_sp++;                                    \
00383     add_ref(_);                                                         \
00384     _sp_->u.program=_;                                                  \
00385     _sp_->type=PIKE_T_PROGRAM;                                          \
00386   }while(0)
00387 
00388 #define ref_push_mapping(M) do{                                         \
00389     struct mapping *_=(M);                                              \
00390     struct svalue *_sp_ = Pike_sp++;                                    \
00391     add_ref(_);                                                         \
00392     _sp_->u.mapping=_;                                                  \
00393     _sp_->type=PIKE_T_MAPPING;                                          \
00394   }while(0)
00395 
00396 #define ref_push_array(A) do{                                           \
00397     struct array *_=(A);                                                \
00398     struct svalue *_sp_ = Pike_sp++;                                    \
00399     add_ref(_);                                                         \
00400     _sp_->u.array=_ ;                                                   \
00401     _sp_->type=PIKE_T_ARRAY;                                            \
00402   }while(0)
00403 
00404 #define ref_push_multiset(L) do{                                        \
00405     struct multiset *_=(L);                                             \
00406     struct svalue *_sp_ = Pike_sp++;                                    \
00407     add_ref(_);                                                         \
00408     _sp_->u.multiset=_;                                                 \
00409     _sp_->type=PIKE_T_MULTISET;                                         \
00410   }while(0)
00411 
00412 #define ref_push_string(S) do{                                          \
00413     struct pike_string *_=(S);                                          \
00414     struct svalue *_sp_ = Pike_sp++;                                    \
00415     DO_IF_DEBUG(if(_->size_shift & ~3) {                                \
00416                   Pike_fatal("Pushing string with bad shift: %d\n",     \
00417                              _->size_shift);                            \
00418                 });                                                     \
00419     add_ref(_);                                                         \
00420     _sp_->subtype=0;                                                    \
00421     _sp_->u.string=_;                                                   \
00422     _sp_->type=PIKE_T_STRING;                                           \
00423   }while(0)
00424 
00425 #define ref_push_type_value(S) do{                                      \
00426     struct pike_type *_=(S);                                            \
00427     struct svalue *_sp_ = Pike_sp++;                                    \
00428     add_ref(_);                                                         \
00429     _sp_->u.type=_;                                                     \
00430     _sp_->type=PIKE_T_TYPE;                                             \
00431   }while(0)
00432 
00433 #define ref_push_object(O) do{                                          \
00434     struct object  *_=(O);                                              \
00435     struct svalue *_sp_ = Pike_sp++;                                    \
00436     add_ref(_);                                                         \
00437     _sp_->u.object=_;                                                   \
00438     _sp_->type=PIKE_T_OBJECT;                                           \
00439     _sp_->subtype = 0;                                                  \
00440   }while(0)
00441 
00442 #define ref_push_object_inherit(O, INH_NUM) do{                         \
00443     struct object  *_ = (O);                                            \
00444     struct svalue *_sp_ = Pike_sp++;                                    \
00445     int _inh_ = (INH_NUM);                                              \
00446     add_ref(_);                                                         \
00447     _sp_->u.object = _;                                                 \
00448     _sp_->type = PIKE_T_OBJECT;                                         \
00449     _sp_->subtype = _inh_;                                              \
00450   }while(0)
00451 
00452 #define ref_push_function(OBJ, FUN) do {                                \
00453     struct object *_=(OBJ);                                             \
00454     struct svalue *_sp_ = Pike_sp++;                                    \
00455     add_ref(_);                                                         \
00456     _sp_->u.object=_;                                                   \
00457     _sp_->subtype=(FUN);                                                \
00458     _sp_->type=PIKE_T_FUNCTION;                                         \
00459   } while (0)
00460 
00461 #define push_svalue(S) do {                                             \
00462     const struct svalue *_=(S);                                         \
00463     struct svalue *_sp_ = Pike_sp++;                                    \
00464     assign_svalue_no_free(_sp_,_);                                      \
00465   }while(0)
00466 
00467 #define stack_dup() push_svalue(Pike_sp-1)
00468 
00469 #define stack_swap() do {                                               \
00470     struct svalue *_sp_ = Pike_sp;                                      \
00471     struct svalue _=_sp_[-1];                                           \
00472     _sp_[-1]=_sp_[-2];                                                  \
00473     _sp_[-2]=_;                                                         \
00474   } while(0)
00475 
00476 #define push_zeroes(N) do{                      \
00477     struct svalue *s_=Pike_sp;                  \
00478     ptrdiff_t num_= (N);                        \
00479     for(;num_-- > 0;s_++)                       \
00480     {                                           \
00481       s_->type=PIKE_T_INT;                      \
00482       s_->subtype=NUMBER_NUMBER;                \
00483       s_->u.integer=0;                          \
00484     }                                           \
00485     Pike_sp=s_;                                 \
00486 }while(0)
00487 
00488 #define push_undefines(N) do{                   \
00489     struct svalue *s_=Pike_sp;                  \
00490     ptrdiff_t num_= (N);                        \
00491     for(;num_-- > 0;s_++)                       \
00492     {                                           \
00493       s_->type=PIKE_T_INT;                      \
00494       s_->subtype=NUMBER_UNDEFINED;             \
00495       s_->u.integer=0;                          \
00496     }                                           \
00497     Pike_sp=s_;                                 \
00498 }while(0)
00499 
00500 #define free_pike_frame(F) do{ struct pike_frame *f_=(F); if(!sub_ref(f_)) really_free_pike_frame(f_); }while(0)
00501 
00502 /* A scope is any frame which may have malloced locals */
00503 #define free_pike_scope(F) do{ struct pike_frame *f_=(F); if(!sub_ref(f_)) really_free_pike_scope(f_); }while(0)
00504 
00505 #define POP_PIKE_FRAME() do {                                           \
00506   struct pike_frame *_fp_ = Pike_fp;                                    \
00507   struct pike_frame *tmp_=_fp_->next;                                   \
00508   DO_IF_PROFILING({                                                     \
00509       /* Time spent in this frame + children. */                        \
00510       cpu_time_t time_passed =                                          \
00511         get_cpu_time() - Pike_interpreter.unlocked_time;                \
00512       /* Time spent in children to this frame. */                       \
00513       cpu_time_t time_in_children;                                      \
00514       /* Time spent in just this frame. */                              \
00515       cpu_time_t self_time;                                             \
00516       struct identifier *function;                                      \
00517       DO_IF_PROFILING_DEBUG({                                           \
00518           fprintf(stderr, "%p}: Pop got %" PRINT_CPU_TIME               \
00519                   " (%" PRINT_CPU_TIME ")"                              \
00520                   " %" PRINT_CPU_TIME " (%" PRINT_CPU_TIME ")\n",       \
00521                   Pike_interpreter.thread_state, time_passed,           \
00522                   _fp_->start_time, Pike_interpreter.accounted_time,    \
00523                   _fp_->children_base);                                 \
00524         });                                                             \
00525       time_passed -= _fp_->start_time;                                  \
00526       DO_IF_DEBUG(if (time_passed < 0) {                                \
00527                     Pike_fatal("Negative time_passed: %" PRINT_CPU_TIME \
00528                                " now: %" PRINT_CPU_TIME                 \
00529                                " unlocked_time: %" PRINT_CPU_TIME       \
00530                                " start_time: %" PRINT_CPU_TIME          \
00531                                "\n", time_passed, get_cpu_time(),       \
00532                                Pike_interpreter.unlocked_time,          \
00533                                _fp_->start_time);                       \
00534                   });                                                   \
00535       time_in_children =                                                \
00536         Pike_interpreter.accounted_time - _fp_->children_base;          \
00537       DO_IF_DEBUG(if (time_in_children < 0) {                           \
00538                     Pike_fatal("Negative time_in_children: %"           \
00539                                PRINT_CPU_TIME                           \
00540                                " accounted_time: %" PRINT_CPU_TIME      \
00541                                " children_base: %" PRINT_CPU_TIME       \
00542                                "\n", time_in_children,                  \
00543                                Pike_interpreter.accounted_time,         \
00544                                _fp_->children_base);                    \
00545                   });                                                   \
00546       self_time = time_passed - time_in_children;                       \
00547       DO_IF_DEBUG(if (self_time < 0) {                                  \
00548                     Pike_fatal("Negative self_time: %" PRINT_CPU_TIME   \
00549                                " time_passed: %" PRINT_CPU_TIME         \
00550                                " time_in_children: %" PRINT_CPU_TIME    \
00551                                "\n", self_time, time_passed,            \
00552                                time_in_children);                       \
00553                   });                                                   \
00554       Pike_interpreter.accounted_time += self_time;                     \
00555       /* FIXME: Can context.prog be NULL? */                            \
00556       function = _fp_->context.prog->identifiers + _fp_->ident;         \
00557       /* function->total_time =                                         \
00558          Pike_fp->self_time_base + time_passed; */                      \
00559       function->total_time += time_passed;                              \
00560       function->self_time += self_time;                                 \
00561     });                                                                 \
00562   if(!sub_ref(_fp_))                                                    \
00563   {                                                                     \
00564     really_free_pike_frame(_fp_);                                       \
00565   }else{                                                                \
00566     ptrdiff_t num_expendible = _fp_->expendible - _fp_->locals;         \
00567     DO_IF_DEBUG(                                                        \
00568       if( (_fp_->locals + _fp_->num_locals > Pike_sp) ||                \
00569           (Pike_sp < _fp_->expendible) ||                               \
00570           (num_expendible < 0) || (num_expendible > _fp_->num_locals))  \
00571         Pike_fatal("Stack failure in POP_PIKE_FRAME %p+%d=%p %p %p!\n", \
00572                    _fp_->locals, _fp_->num_locals,                      \
00573                    _fp_->locals+_fp_->num_locals,                       \
00574                    Pike_sp,_fp_->expendible));                          \
00575     debug_malloc_touch(_fp_);                                           \
00576     if(num_expendible)                                                  \
00577     {                                                                   \
00578       struct svalue *s=(struct svalue *)xalloc(sizeof(struct svalue)*   \
00579                                                num_expendible);         \
00580       _fp_->num_locals = num_expendible;                                \
00581       assign_svalues_no_free(s, _fp_->locals, num_expendible,           \
00582                              BIT_MIXED);                                \
00583       _fp_->locals=s;                                                   \
00584       _fp_->flags|=PIKE_FRAME_MALLOCED_LOCALS;                          \
00585     }else{                                                              \
00586       _fp_->locals=0;                                                   \
00587     }                                                                   \
00588     _fp_->next=0;                                                       \
00589   }                                                                     \
00590   Pike_fp=tmp_;                                                         \
00591  }while(0)
00592 
00593 
00594 enum apply_type
00595 {
00596   APPLY_STACK, /* The function is the first argument */
00597   APPLY_SVALUE, /* arg1 points to an svalue containing the function */
00598   APPLY_SVALUE_STRICT, /* Like APPLY_SVALUE, but does not return values for void functions */
00599    APPLY_LOW    /* arg1 is the object pointer,(int)arg2 the function */
00600 };
00601 
00602 #define APPLY_MASTER(FUN,ARGS) \
00603 do{ \
00604   static int fun_, master_cnt=0; \
00605   struct object *master_ob=master(); \
00606   if(master_cnt != master_ob->prog->id) \
00607   { \
00608     fun_=find_identifier(FUN,master_ob->prog); \
00609     master_cnt = master_ob->prog->id; \
00610   } \
00611   apply_low(master_ob, fun_, ARGS); \
00612 }while(0)
00613 
00614 #define SAFE_APPLY_MASTER(FUN,ARGS) \
00615 do{ \
00616   static int fun_, master_cnt=0; \
00617   struct object *master_ob=master(); \
00618   if(master_cnt != master_ob->prog->id) \
00619   { \
00620     fun_=find_identifier(FUN,master_ob->prog); \
00621     master_cnt = master_ob->prog->id; \
00622   } \
00623   safe_apply_low2(master_ob, fun_, ARGS, 1); \
00624 }while(0)
00625 
00626 #define SAFE_APPLY_HANDLER(FUN, HANDLER, COMPAT, ARGS) do {     \
00627     static int h_fun_=-1, h_id_=0;                              \
00628     static int c_fun_=-1, c_fun_id_=0;                          \
00629     struct object *h_=(HANDLER), *c_=(COMPAT);                  \
00630     if (h_ && h_->prog) {                                       \
00631       if (h_->prog->id != h_id_) {                              \
00632         h_fun_ = find_identifier(fun, h_->prog);                \
00633         h_id_ = h_->prog->id;                                   \
00634       }                                                         \
00635       if (h_fun_ != -1) {                                       \
00636         safe_apply_low(h_, h_fun_, ARGS);                       \
00637         break;                                                  \
00638       }                                                         \
00639     }                                                           \
00640     if (c_ && c_->prog) {                                       \
00641       if (c_->prog->id != c_id_) {                              \
00642         c_fun_ = find_identifier(fun, c_->prog);                \
00643         c_id_ = c_->prog->id;                                   \
00644       }                                                         \
00645       if (c_fun_ != -1) {                                       \
00646         safe_apply_low(c_, c_fun_, ARGS);                       \
00647         break;                                                  \
00648       }                                                         \
00649     }                                                           \
00650     SAFE_APPLY_MASTER(FUN, ARGS);                               \
00651   } while(0)
00652 
00653 
00654 #ifdef INTERNAL_PROFILING
00655 PMOD_EXPORT extern unsigned long evaluator_callback_calls;
00656 #endif
00657 
00658 #define check_threads_etc() do { \
00659   DO_IF_INTERNAL_PROFILING (evaluator_callback_calls++); \
00660   call_callback(& evaluator_callbacks, NULL); \
00661 }while(0) 
00662 
00663 #ifdef PIKE_DEBUG
00664 #define fast_check_threads_etc(X) do { \
00665   static int div_; if(d_flag || !(div_++& ((1<<(X))-1))) check_threads_etc(); } while(0)
00666 
00667 #else
00668 #define fast_check_threads_etc(X) do { \
00669   static int div_; if(!(div_++& ((1<<(X))-1))) check_threads_etc(); } while(0)
00670 #endif
00671 
00672 #include "block_alloc_h.h"
00673 /* Prototypes begin here */
00674 void push_sp_mark(void);
00675 ptrdiff_t pop_sp_mark(void);
00676 void gc_mark_stack_external (struct pike_frame *frame,
00677                              struct svalue *stack_p, struct svalue *stack);
00678 PMOD_EXPORT int low_init_interpreter(struct Pike_interpreter *interpreter);
00679 PMOD_EXPORT void init_interpreter(void);
00680 void lvalue_to_svalue_no_free(struct svalue *to,struct svalue *lval);
00681 PMOD_EXPORT void assign_lvalue(struct svalue *lval,struct svalue *from);
00682 PMOD_EXPORT union anything *get_pointer_if_this_type(struct svalue *lval, TYPE_T t);
00683 void print_return_value(void);
00684 void reset_evaluator(void);
00685 struct backlog;
00686 void dump_backlog(void);
00687 BLOCK_ALLOC(pike_frame,128);
00688 
00689 #ifdef PIKE_USE_MACHINE_CODE
00690 #if defined(OPCODE_INLINE_BRANCH) || defined(INS_F_JUMP) || \
00691     defined(INS_F_JUMP_WITH_ARG) || defined(INS_F_JUMP_WITH_TWO_ARGS)
00692 void branch_check_threads_etc();
00693 #endif
00694 #ifdef PIKE_DEBUG
00695 void simple_debug_instr_prologue_0 (PIKE_INSTR_T instr);
00696 void simple_debug_instr_prologue_1 (PIKE_INSTR_T instr, INT32 arg);
00697 void simple_debug_instr_prologue_2 (PIKE_INSTR_T instr, INT32 arg1, INT32 arg2);
00698 #endif
00699 #endif  /* PIKE_USE_MACHINE_CODE */
00700 
00701 PMOD_EXPORT void find_external_context(struct external_variable_context *loc,
00702                                        int arg2);
00703 void really_free_pike_scope(struct pike_frame *scope);
00704 int low_mega_apply(enum apply_type type, INT32 args, void *arg1, void *arg2);
00705 void low_return(void);
00706 void low_return_pop(void);
00707 void unlink_previous_frame(void);
00708 void mega_apply(enum apply_type type, INT32 args, void *arg1, void *arg2);
00709 PMOD_EXPORT void f_call_function(INT32 args);
00710 PMOD_EXPORT void call_handle_error(void);
00711 PMOD_EXPORT int apply_low_safe_and_stupid(struct object *o, INT32 offset);
00712 PMOD_EXPORT void safe_apply_low(struct object *o,int fun,int args);
00713 PMOD_EXPORT void safe_apply_low2(struct object *o,int fun,int args, int handle_errors);
00714 PMOD_EXPORT void safe_apply_low3(struct object *o,int fun,int args, char *error);
00715 PMOD_EXPORT void safe_apply(struct object *o, const char *fun ,INT32 args);
00716 PMOD_EXPORT int low_unsafe_apply_handler(const char *fun,
00717                                          struct object *handler,
00718                                          struct object *compat,
00719                                          INT32 args);
00720 PMOD_EXPORT void low_safe_apply_handler(const char *fun,
00721                                         struct object *handler,
00722                                         struct object *compat,
00723                                         INT32 args);
00724 PMOD_EXPORT int safe_apply_handler(const char *fun,
00725                                    struct object *handler,
00726                                    struct object *compat,
00727                                    INT32 args,
00728                                    TYPE_FIELD rettypes);
00729 PMOD_EXPORT void apply_lfun(struct object *o, int fun, int args);
00730 PMOD_EXPORT void apply_shared(struct object *o,
00731                   struct pike_string *fun,
00732                   int args);
00733 PMOD_EXPORT void apply(struct object *o, const char *fun, int args);
00734 PMOD_EXPORT void apply_svalue(struct svalue *s, INT32 args);
00735 PMOD_EXPORT void safe_apply_svalue (struct svalue *s, INT32 args, int handle_errors);
00736 PMOD_EXPORT void apply_external(int depth, int fun, INT32 args);
00737 PMOD_EXPORT void slow_check_stack(void);
00738 PMOD_EXPORT void custom_check_stack(ptrdiff_t amount, const char *fmt, ...)
00739   ATTRIBUTE((format (printf, 2, 3)));
00740 PMOD_EXPORT void cleanup_interpret(void);
00741 PMOD_EXPORT void low_cleanup_interpret(struct Pike_interpreter *interpreter);
00742 void really_clean_up_interpret(void);
00743 /* Prototypes end here */
00744 
00745 /* These need to be after the prototypes,
00746  * to avoid implicit declaration of mega_apply().
00747  */
00748 #ifdef __ECL
00749 static INLINE void apply_low(struct object *o, ptrdiff_t fun, INT32 args)
00750 {
00751   mega_apply(APPLY_LOW, args, (void*)o, (void*)fun);
00752 }
00753 
00754 static INLINE void strict_apply_svalue(struct svalue *sval, INT32 args)
00755 {
00756   mega_apply(APPLY_SVALUE_STRICT, args, (void*)sval, 0);
00757 }
00758 #else /* !__ECL */
00759 #define apply_low(O,FUN,ARGS) \
00760   mega_apply(APPLY_LOW, (ARGS), (void*)(O),(void*)(ptrdiff_t)(FUN))
00761 
00762 #define strict_apply_svalue(SVAL,ARGS) \
00763   mega_apply(APPLY_SVALUE, (ARGS), (void*)(SVAL),0)
00764 #endif /* __ECL */
00765 
00766 #define apply_current(FUN, ARGS)                        \
00767   apply_low(Pike_fp->current_object,                    \
00768             (FUN) + Pike_fp->context.identifier_level,  \
00769             (ARGS))
00770 
00771 PMOD_EXPORT extern int d_flag; /* really in main.c */
00772 
00773 PMOD_EXPORT extern int Pike_stack_size;
00774 PMOD_EXPORT struct callback;
00775 PMOD_EXPORT extern struct callback_list evaluator_callbacks;
00776 
00777 /* Things to try:
00778  * we could reduce thread swapping to a pointer operation if
00779  * we do something like:
00780  *   #define Pike_interpreter (*Pike_interpreter_pointer)
00781  *
00782  * Since global variables are usually accessed through indirection
00783  * anyways, it might not make any speed differance.
00784  *
00785  * The above define could also be used to facilitate dynamic loading
00786  * on Win32..
00787  */
00788 PMOD_EXPORT extern struct Pike_interpreter Pike_interpreter;
00789 
00790 #define Pike_sp Pike_interpreter.stack_pointer
00791 #define Pike_fp Pike_interpreter.frame_pointer
00792 #define Pike_mark_sp Pike_interpreter.mark_stack_pointer
00793 
00794 
00795 #define CURRENT_STORAGE (dmalloc_touch(struct pike_frame *,Pike_fp)->current_storage)
00796 
00797 
00798 #define PIKE_STACK_MMAPPED
00799 
00800 struct Pike_stack
00801 {
00802   struct svalue *top;
00803   int flags;
00804   struct Pike_stack *previous;
00805   struct svalue *save_ptr;
00806   struct svalue stack[1];
00807 };
00808 
00809 
00810 #define PIKE_STACK_REQUIRE_BEGIN(num, base) do {                        \
00811   struct Pike_stack *old_stack_;                                        \
00812   if(Pike_interpreter.current_stack->top - Pike_sp < num)               \
00813   {                                                                     \
00814     old_stack_=Pike_interpreter.current_stack;                          \
00815     old_stack_->save_ptr=Pike_sp;                                       \
00816     Pike_interpreter.current_stack=allocate_array(MAXIMUM(num, 8192));  \
00817     while(old_sp > base) *(Pike_sp++) = *--old_stack_->save_ptr;        \
00818   }
00819 
00820 #define PIKE_STACK_REQUIRE_END()                                           \
00821   while(Pike_sp > Pike_interpreter.current_stack->stack)                   \
00822     *(old_stack_->save_ptr++) = *--Pike_sp;                                \
00823   Pike_interpreter.current_stack=Pike_interpreter.current_stack->previous; \
00824 }while(0)  
00825 
00826 #endif

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