00001
00002
00003
00004
00005
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
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;
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
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
00178 #define STACK_LEVEL_START(depth) do {
00179 #define STACK_LEVEL_DONE(depth) } while(0)
00180 #define STACK_LEVEL_CHECK(depth)
00181 #endif
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
00189 #define MAYBE_CAST_TO_LONG(X) ((long)(X))
00190 #endif
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
00206
00207
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
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 \
00510 cpu_time_t time_passed = \
00511 get_cpu_time() - Pike_interpreter.unlocked_time; \
00512 \
00513 cpu_time_t time_in_children; \
00514 \
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 \
00556 function = _fp_->context.prog->identifiers + _fp_->ident; \
00557
00558 \
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,
00597 APPLY_SVALUE,
00598 APPLY_SVALUE_STRICT,
00599 APPLY_LOW
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
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
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
00744
00745
00746
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
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
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;
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
00778
00779
00780
00781
00782
00783
00784
00785
00786
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