e576bb2002-10-11Martin Nilsson /* || This file is part of Pike. For copyright information see COPYRIGHT. || Pike is distributed under GPL, LGPL and MPL. See the file COPYING || for more information. */
24ddc71998-03-28Henrik Grubbström (Grubba) 
5267b71995-08-09Fredrik Hübinette (Hubbe) #ifndef INTERPRET_H #define INTERPRET_H
442aea1997-01-28Fredrik Hübinette (Hubbe) #include "global.h"
5267b71995-08-09Fredrik Hübinette (Hubbe) #include "program.h"
b2d3e42000-12-01Fredrik Hübinette (Hubbe) #include "pike_error.h"
b9114d2004-03-06Martin Nilsson #include "object.h"
b2630d2004-05-20Henrik Grubbström (Grubba) #include "pike_rusage.h"
26da462017-02-21Martin Karlgren #include "pikecode.h"
ec2bab2000-06-24Fredrik Hübinette (Hubbe) 
ca176b2006-02-27Martin Stjernholm struct catch_context { struct catch_context *prev; JMP_BUF recovery; struct svalue *save_expendible; PIKE_OPCODE_T *next_addr; ptrdiff_t continue_reladdr; #ifdef PIKE_DEBUG struct pike_frame *frame; #endif };
d97eb72011-07-10Henrik Grubbström (Grubba) struct Pike_interpreter_struct {
ec2bab2000-06-24Fredrik Hübinette (Hubbe)  /* Swapped variables */
5923b12000-07-06Fredrik Hübinette (Hubbe)  struct svalue *stack_pointer; struct svalue *evaluator_stack;
17f08c2000-07-06Fredrik Hübinette (Hubbe)  struct svalue **mark_stack_pointer;
5923b12000-07-06Fredrik Hübinette (Hubbe)  struct svalue **mark_stack; struct pike_frame *frame_pointer;
ec2bab2000-06-24Fredrik Hübinette (Hubbe)  JMP_BUF *recoveries;
f077582000-07-06Fredrik Hübinette (Hubbe) #ifdef PIKE_THREADS
0431312003-02-15Henrik Grubbström (Grubba)  struct thread_state *thread_state;
f077582000-07-06Fredrik Hübinette (Hubbe) #endif
5923b12000-07-06Fredrik Hübinette (Hubbe)  char *stack_top;
ec2bab2000-06-24Fredrik Hübinette (Hubbe) 
ca176b2006-02-27Martin Stjernholm  struct catch_context *catch_ctx;
50f6262015-11-27Henrik Grubbström (Grubba)  LOW_JMP_BUF *catching_eval_jmpbuf;
ca176b2006-02-27Martin Stjernholm 
6697042000-11-20Martin Stjernholm  int svalue_stack_margin; int c_stack_margin;
ca176b2006-02-27Martin Stjernholm  INT16 evaluator_stack_malloced; INT16 mark_stack_malloced;
ec2bab2000-06-24Fredrik Hübinette (Hubbe) #ifdef PROFILING
ddf41c2005-07-22Martin Nilsson  cpu_time_t accounted_time; /** Time spent and accounted for so far. */ cpu_time_t unlocked_time; /** Time spent unlocked so far. */
0612442001-05-16Fredrik Hübinette (Hubbe)  char *stack_bottom;
ec2bab2000-06-24Fredrik Hübinette (Hubbe) #endif
6198092003-01-08Martin Stjernholm  int trace_level;
ec2bab2000-06-24Fredrik Hübinette (Hubbe) };
5267b71995-08-09Fredrik Hübinette (Hubbe) 
dfa5b31996-12-05Fredrik Hübinette (Hubbe) #ifndef STRUCT_FRAME_DECLARED #define STRUCT_FRAME_DECLARED #endif
4218011999-01-31Fredrik Hübinette (Hubbe) struct pike_frame
5267b71995-08-09Fredrik Hübinette (Hubbe) {
ddf41c2005-07-22Martin Nilsson  INT32 refs;/* must be first */
bca80a2016-07-18Arne Goedeke  /* The folloing fields are only used during setup and teardown */
f2db212016-07-04Arne Goedeke  unsigned INT16 fun; /** Function number. */
bca80a2016-07-18Arne Goedeke  INT16 ident; /** Function identifier offset */ struct pike_frame *next; /** parent frame */ struct pike_frame *scope; /** scope */ struct svalue **save_mark_sp; /** saved mark sp level */
ddf41c2005-07-22Martin Nilsson  PIKE_OPCODE_T *pc; /** Address of current opcode. */ struct svalue *locals; /** Start of local variables. */
bca80a2016-07-18Arne Goedeke  char *current_storage; /** == current_object->storage + context->storage_offset */ struct object *current_object; struct inherit *context; /** inherit context */ struct program *current_program; /* program containing the context. */ PIKE_OPCODE_T *return_addr; /** Address of opcode to continue at after call. */
9ddbf22001-05-10Fredrik Hübinette (Hubbe) 
eb29d92016-11-04Martin Karlgren  /** * If PIKE_FRAME_SAVE_LOCALS is set, this is a pointer to a bitmask * represented by an array of 16-bit ints. A set bit indicates that * the corresponding local variable is used from a subscope and * needs to be preserved in LOW_POP_PIKE_FRAME. The least * significant bit of the first entry represents the first local * variable and so on. The array is (num_locals >> 4) + 1 entries * (i.e. it will always have enough space to represent all * locals). */ unsigned INT16 *save_locals_bitmask;
bca80a2016-07-18Arne Goedeke  unsigned INT16 flags; /** PIKE_FRAME_* */ /** * This tells us the current level of svalues on the stack that can * be discarded once the current function is done with them. It is an offset * from locals and is always positive.
9ddbf22001-05-10Fredrik Hübinette (Hubbe)  */
bca80a2016-07-18Arne Goedeke  INT16 expendible_offset; INT16 num_locals; /** Number of local variables. */ INT16 num_args; /** Number of argument variables. */
9ddbf22001-05-10Fredrik Hübinette (Hubbe) 
bca80a2016-07-18Arne Goedeke  INT32 args; /** Actual number of arguments passed to the function. */
ddf41c2005-07-22Martin Nilsson  /**
bca80a2016-07-18Arne Goedeke  * This is an offset from locals and denotes the place where the return value * should go. * * It can be -1 if the function to be called is on the stack. * It can be even more negative in case of recursion when the return value location * get replaced by that of the previous frame.
9ddbf22001-05-10Fredrik Hübinette (Hubbe)  */
bca80a2016-07-18Arne Goedeke  INT16 save_sp_offset;
9ddbf22001-05-10Fredrik Hübinette (Hubbe) 
fcca612016-02-11Martin Nilsson #ifdef PROFILING
ddf41c2005-07-22Martin Nilsson  cpu_time_t children_base; /** Accounted time when the frame started. */ cpu_time_t start_time; /** Adjusted time when thr frame started. */
fcca612016-02-11Martin Nilsson #endif /* PROFILING */
5267b71995-08-09Fredrik Hübinette (Hubbe) };
bca80a2016-07-18Arne Goedeke static inline struct svalue *frame_get_save_sp(const struct pike_frame *frame) { return frame->locals + frame->save_sp_offset; } static inline void frame_set_save_sp(struct pike_frame *frame, struct svalue *sv) { ptrdiff_t n = sv - frame->locals; #ifdef PIKE_DEBUG if (n < MIN_INT16 || n > MAX_INT16) Pike_error("Save SP offset too large.\n"); #endif frame->save_sp_offset = n; } static inline struct svalue *frame_get_expendible(const struct pike_frame *frame) { return frame->locals + frame->expendible_offset; } static inline void frame_set_expendible(struct pike_frame *frame, struct svalue *sv) { ptrdiff_t n = sv - frame->locals; #ifdef PIKE_DEBUG if (n < MIN_INT16 || n > MAX_INT16) Pike_error("Expendible offset too large.\n"); #endif frame->expendible_offset = n; }
9ddbf22001-05-10Fredrik Hübinette (Hubbe) #define PIKE_FRAME_RETURN_INTERNAL 1 #define PIKE_FRAME_RETURN_POP 2
9d52082016-10-30Martin Karlgren #define PIKE_FRAME_SAVE_LOCALS 0x4000 /* save_locals_bitmask is set */
9ddbf22001-05-10Fredrik Hübinette (Hubbe) #define PIKE_FRAME_MALLOCED_LOCALS 0x8000
ff5c352017-07-05Henrik Grubbström (Grubba) #define PIKE_FRAME_RETURN_MASK (PIKE_FRAME_RETURN_INTERNAL|PIKE_FRAME_RETURN_POP) #define PIKE_FRAME_LOCALS_MASK (PIKE_FRAME_SAVE_LOCALS|PIKE_FRAME_MALLOCED_LOCALS)
342fef2000-08-23Fredrik Hübinette (Hubbe) struct external_variable_context { struct object *o; struct inherit *inherit; int parent_identifier; };
7df3482001-07-21Henrik Grubbström (Grubba) 
7666f82014-06-19Per Hedbor 
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
c299402001-11-10Martin Stjernholm PMOD_EXPORT extern const char msg_stack_error[];
f9bafd2008-12-12Martin Stjernholm #define debug_check_stack() do{if(Pike_sp<Pike_interpreter.evaluator_stack)Pike_fatal("%s", msg_stack_error);}while(0)
5aad932002-08-15Marcus Comstedt #define check__positive(X,Y) if((X)<0) Pike_fatal Y
5267b71995-08-09Fredrik Hübinette (Hubbe) #else
9649491998-02-27Fredrik Hübinette (Hubbe) #define check__positive(X,Y)
13670c2015-05-25Martin Nilsson #define debug_check_stack()
5267b71995-08-09Fredrik Hübinette (Hubbe) #endif
fa382f1996-06-21Fredrik Hübinette (Hubbe) 
c915472000-12-04Martin Stjernholm #define low_stack_check(X) \ (Pike_sp - Pike_interpreter.evaluator_stack + \ Pike_interpreter.svalue_stack_margin + (X) >= Pike_stack_size)
c299402001-11-10Martin Stjernholm PMOD_EXPORT extern const char Pike_check_stack_errmsg[];
c915472000-12-04Martin Stjernholm 
6f95902000-08-17Henrik Grubbström (Grubba) #define check_stack(X) do { \
c915472000-12-04Martin Stjernholm  if(low_stack_check(X)) \
b1197a2000-12-28Henrik Grubbström (Grubba)  ((void (*)(const char *, ...))Pike_error)( \ Pike_check_stack_errmsg, \
6da27e2016-02-12Martin Nilsson  (long)(Pike_sp - Pike_interpreter.evaluator_stack), \ (long)Pike_stack_size, \ (long)(X)); \
7e97c31999-01-21Fredrik Hübinette (Hubbe)  }while(0)
c299402001-11-10Martin Stjernholm PMOD_EXPORT extern const char Pike_check_mark_stack_errmsg[];
c915472000-12-04Martin Stjernholm 
7e97c31999-01-21Fredrik Hübinette (Hubbe) #define check_mark_stack(X) do { \
b1197a2000-12-28Henrik Grubbström (Grubba)  if(Pike_mark_sp - Pike_interpreter.mark_stack + (X) >= Pike_stack_size) \ ((void (*)(const char*, ...))Pike_error)(Pike_check_mark_stack_errmsg); \
7e97c31999-01-21Fredrik Hübinette (Hubbe)  }while(0)
c299402001-11-10Martin Stjernholm PMOD_EXPORT extern const char Pike_check_c_stack_errmsg[];
c915472000-12-04Martin Stjernholm 
4779702009-04-01Martin Stjernholm #define low_check_c_stack(MIN_BYTES, RUN_IF_LOW) do { \
2059f32006-03-25Henrik Grubbström (Grubba)  ptrdiff_t x_= (((char *)&x_) - Pike_interpreter.stack_top) + \
4779702009-04-01Martin Stjernholm  STACK_DIRECTION * (MIN_BYTES); \ x_*=STACK_DIRECTION; \ if(x_>0) {RUN_IF_LOW;} \ } while (0) #define check_c_stack(MIN_BYTES) do { \ low_check_c_stack (Pike_interpreter.c_stack_margin + (MIN_BYTES), { \ low_error(Pike_check_c_stack_errmsg); \ /* Pike_fatal("C stack overflow: x_:%p &x_:%p top:%p margin:%p\n", \ x_, &x_, Pike_interpreter.stack_top, \ Pike_interpreter.c_stack_margin + (MIN_BYTES)); */ \ }); \
7e97c31999-01-21Fredrik Hübinette (Hubbe)  }while(0)
4779702009-04-01Martin Stjernholm #define fatal_check_c_stack(MIN_BYTES) do { \ low_check_c_stack ((MIN_BYTES), { \ ((void (*)(const char*, ...))Pike_fatal)(Pike_check_c_stack_errmsg); \ }); \
fffb2a2000-09-12Henrik Grubbström (Grubba)  }while(0)
2827f82017-10-09Martin Karlgren PMOD_EXPORT extern void check_c_stack_margin(void);
7e97c31999-01-21Fredrik Hübinette (Hubbe) 
938a5d2002-10-12Henrik Grubbström (Grubba) #ifdef PIKE_DEBUG #define STACK_LEVEL_START(depth) \ do { \
e7a7142002-11-23Martin Stjernholm  struct svalue *save_stack_level = (Pike_sp - (depth))
938a5d2002-10-12Henrik Grubbström (Grubba)  #define STACK_LEVEL_DONE(depth) \ STACK_LEVEL_CHECK(depth); \ } while(0) #define STACK_LEVEL_CHECK(depth) \ do { \ if (Pike_sp != save_stack_level + (depth)) { \ Pike_fatal("Unexpected stack level! " \ "Actual: %d, expected: %d\n", \
cc7cf42015-10-14Martin Nilsson  (int)(Pike_sp - save_stack_level), \
938a5d2002-10-12Henrik Grubbström (Grubba)  (depth)); \ } \ } while(0) #else /* !PIKE_DEBUG */ #define STACK_LEVEL_START(depth) do { #define STACK_LEVEL_DONE(depth) } while(0) #define STACK_LEVEL_CHECK(depth) #endif /* PIKE_DEBUG */
996aa52010-11-19Henrik Grubbström (Grubba) #ifdef __CHECKER__
722f712014-06-28Henrik Grubbström (Grubba) #define SET_SVAL_TYPE_CHECKER(S,T) SET_SVAL_TYPE_SUBTYPE(S,T,0)
996aa52010-11-19Henrik Grubbström (Grubba) #else
722f712014-06-28Henrik Grubbström (Grubba) #define SET_SVAL_TYPE_CHECKER(S,T) SET_SVAL_TYPE_DC(S,T)
996aa52010-11-19Henrik Grubbström (Grubba) #endif
15a05f2002-11-23Martin Stjernholm #define pop_stack() do{ free_svalue(--Pike_sp); debug_check_stack(); }while(0)
2ac9502001-08-14Fredrik Hübinette (Hubbe) #define pop_2_elems() do { pop_stack(); pop_stack(); }while(0)
2d12341997-03-10Fredrik Hübinette (Hubbe) 
c299402001-11-10Martin Stjernholm PMOD_EXPORT extern const char msg_pop_neg[];
3469ac2000-08-03Henrik Grubbström (Grubba) #define pop_n_elems(X) \
87a4162003-04-27Martin Stjernholm  do { \ ptrdiff_t x_=(X); \ if(x_) { \ struct svalue *_sp_; \ check__positive(x_, (msg_pop_neg, x_)); \ _sp_ = Pike_sp = Pike_sp - x_; \ debug_check_stack(); \ free_mixed_svalues(_sp_, x_); \ } \ } while (0)
9649491998-02-27Fredrik Hübinette (Hubbe) 
a6d61a2003-04-25Martin Stjernholm /* This pops a number of arguments from the stack but keeps the top * element on top. Used for popping the arguments while keeping the * return value. */ #define stack_unlink(X) do { \
db17192003-04-27Martin Stjernholm  ptrdiff_t x2_ = (X); \ if (x2_) { \
87a4162003-04-27Martin Stjernholm  struct svalue *_sp_ = --Pike_sp; \
db17192003-04-27Martin Stjernholm  free_svalue (_sp_ - x2_); \ move_svalue (_sp_ - x2_, _sp_); \ pop_n_elems (x2_ - 1); \
a6d61a2003-04-25Martin Stjernholm  } \ }while(0) #define stack_pop_n_elems_keep_top(X) stack_unlink(X)
87a4162003-04-27Martin Stjernholm #define stack_pop_keep_top() do { \ struct svalue *_sp_ = --Pike_sp; \ free_svalue (_sp_ - 1); \
db17192003-04-27Martin Stjernholm  move_svalue (_sp_ - 1, _sp_); \
87a4162003-04-27Martin Stjernholm  debug_check_stack(); \ } while (0)
b0d33f2003-04-27Martin Stjernholm #define stack_pop_2_elems_keep_top() do { \ struct svalue *_sp_ = Pike_sp = Pike_sp - 2; \ free_svalue (_sp_ - 1); \ free_svalue (_sp_); \ move_svalue (_sp_ - 1, _sp_ + 1); \ debug_check_stack(); \ } while (0)
a6d61a2003-04-25Martin Stjernholm #define stack_pop_to_no_free(X) move_svalue(X, --Pike_sp) #define stack_pop_to(X) do { \ struct svalue *_=(X); \ free_svalue(_); \ stack_pop_to_no_free(_); \ }while(0) #define push_program(P) do{ \ struct program *_=(P); \
a5cf652014-06-24Henrik Grubbström (Grubba)  struct svalue *_sp_ = Pike_sp++; \
a6d61a2003-04-25Martin Stjernholm  debug_malloc_touch(_); \
722f712014-06-28Henrik Grubbström (Grubba)  SET_SVAL_TYPE_CHECKER(*_sp_, PIKE_T_PROGRAM); \
a6d61a2003-04-25Martin Stjernholm  _sp_->u.program=_; \ }while(0) #define push_int(I) do{ \ INT_TYPE _=(I); \
a5cf652014-06-24Henrik Grubbström (Grubba)  struct svalue *_sp_ = Pike_sp++; \
7666f82014-06-19Per Hedbor  SET_SVAL_TYPE_SUBTYPE(*_sp_, PIKE_T_INT,NUMBER_NUMBER); \
a6d61a2003-04-25Martin Stjernholm  _sp_->u.integer=_; \ }while(0) #define push_undefined() do{ \
a5cf652014-06-24Henrik Grubbström (Grubba)  struct svalue *_sp_ = Pike_sp++; \
7666f82014-06-19Per Hedbor  SET_SVAL_TYPE_SUBTYPE(*_sp_, PIKE_T_INT,NUMBER_UNDEFINED); \
a6d61a2003-04-25Martin Stjernholm  _sp_->u.integer=0; \ }while(0)
7b008b2005-06-20Henrik Grubbström (Grubba) #define push_obj_index(I) do{ \ int _=(I); \ struct svalue *_sp_ = Pike_sp++; \
722f712014-06-28Henrik Grubbström (Grubba)  SET_SVAL_TYPE_CHECKER(*_sp_, T_OBJ_INDEX); \
7b008b2005-06-20Henrik Grubbström (Grubba)  _sp_->u.identifier=_; \ }while(0)
a6d61a2003-04-25Martin Stjernholm #define push_mapping(M) do{ \ struct mapping *_=(M); \
379c892003-04-25Martin Stjernholm  struct svalue *_sp_ = Pike_sp++; \
a6d61a2003-04-25Martin Stjernholm  debug_malloc_touch(_); \
722f712014-06-28Henrik Grubbström (Grubba)  SET_SVAL_TYPE_CHECKER(*_sp_, PIKE_T_MAPPING); \
a6d61a2003-04-25Martin Stjernholm  _sp_->u.mapping=_; \ }while(0) #define push_array(A) do{ \ struct array *_=(A); \
379c892003-04-25Martin Stjernholm  struct svalue *_sp_ = Pike_sp++; \
a6d61a2003-04-25Martin Stjernholm  debug_malloc_touch(_); \
722f712014-06-28Henrik Grubbström (Grubba)  SET_SVAL_TYPE_CHECKER(*_sp_, PIKE_T_ARRAY); \
a6d61a2003-04-25Martin Stjernholm  _sp_->u.array=_ ; \ }while(0)
99a30b2005-05-05Martin Nilsson #define push_empty_array() ref_push_array(&empty_array)
a6d61a2003-04-25Martin Stjernholm #define push_multiset(L) do{ \ struct multiset *_=(L); \
379c892003-04-25Martin Stjernholm  struct svalue *_sp_ = Pike_sp++; \
a6d61a2003-04-25Martin Stjernholm  debug_malloc_touch(_); \
722f712014-06-28Henrik Grubbström (Grubba)  SET_SVAL_TYPE_CHECKER(*_sp_, PIKE_T_MULTISET); \
a6d61a2003-04-25Martin Stjernholm  _sp_->u.multiset=_; \ }while(0) #define push_string(S) do { \ struct pike_string *_=(S); \
a5cf652014-06-24Henrik Grubbström (Grubba)  struct svalue *_sp_ = Pike_sp++; \
a6d61a2003-04-25Martin Stjernholm  debug_malloc_touch(_); \
1714452003-12-23Henrik Grubbström (Grubba)  DO_IF_DEBUG(if(_->size_shift & ~3) { \ Pike_fatal("Pushing string with bad shift: %d\n", \ _->size_shift); \ }); \
7666f82014-06-19Per Hedbor  SET_SVAL_TYPE_SUBTYPE(*_sp_, PIKE_T_STRING,0); \
a6d61a2003-04-25Martin Stjernholm  _sp_->u.string=_; \ }while(0)
99a30b2005-05-05Martin Nilsson #define push_empty_string() ref_push_string(empty_pike_string)
c1dfb32016-03-18Martin Nilsson PMOD_EXPORT void push_random_string(unsigned len);
99a30b2005-05-05Martin Nilsson 
a6d61a2003-04-25Martin Stjernholm #define push_type_value(S) do{ \ struct pike_type *_=(S); \
379c892003-04-25Martin Stjernholm  struct svalue *_sp_ = Pike_sp++; \
a6d61a2003-04-25Martin Stjernholm  debug_malloc_touch(_); \
722f712014-06-28Henrik Grubbström (Grubba)  SET_SVAL_TYPE_CHECKER(*_sp_, PIKE_T_TYPE); \
a6d61a2003-04-25Martin Stjernholm  _sp_->u.type=_; \ }while(0)
7666f82014-06-19Per Hedbor #define push_object(O) push_object_inherit(O,0)
f69fe52004-12-18Henrik Grubbström (Grubba)  #define push_object_inherit(O, INH_NUM) do { \ struct object *_ = (O); \
a5cf652014-06-24Henrik Grubbström (Grubba)  struct svalue *_sp_ = Pike_sp++; \
f69fe52004-12-18Henrik Grubbström (Grubba)  int _inh_ = (INH_NUM); \ debug_malloc_touch(_); \
7666f82014-06-19Per Hedbor  SET_SVAL_TYPE_SUBTYPE(*_sp_, PIKE_T_OBJECT,_inh_); \
f69fe52004-12-18Henrik Grubbström (Grubba)  _sp_->u.object = _; \
a6d61a2003-04-25Martin Stjernholm  }while(0) #define push_float(F) do{ \ FLOAT_TYPE _=(F); \
379c892003-04-25Martin Stjernholm  struct svalue *_sp_ = Pike_sp++; \
722f712014-06-28Henrik Grubbström (Grubba)  SET_SVAL_TYPE_CHECKER(*_sp_, PIKE_T_FLOAT); \
a6d61a2003-04-25Martin Stjernholm  _sp_->u.float_number=_; \ }while(0)
bf76fe2014-05-22Per Hedbor PMOD_EXPORT extern void push_text( const char *x );
75367d2014-08-22Arne Goedeke PMOD_EXPORT extern void push_static_text( const char *x );
0542ef1999-11-17Fredrik Hübinette (Hubbe) 
a6d61a2003-04-25Martin Stjernholm #define push_constant_text(T) do{ \
0c942a2017-10-31Arne Goedeke  struct svalue *_sp_ = Pike_sp; \
7666f82014-06-19Per Hedbor  SET_SVAL_TYPE_SUBTYPE(*_sp_, PIKE_T_STRING,0); \
a6d61a2003-04-25Martin Stjernholm  REF_MAKE_CONST_STRING(_sp_->u.string,T); \
0c942a2017-10-31Arne Goedeke  Pike_sp = _sp_ + 1; \
a6d61a2003-04-25Martin Stjernholm  }while(0)
aceb582005-05-27Martin Stjernholm  #define push_constant_string_code(STR, CODE) do{ \ struct pike_string *STR; \ REF_MAKE_CONST_STRING_CODE (STR, CODE); \ push_string (STR); \ }while(0)
a6d61a2003-04-25Martin Stjernholm  #define push_function(OBJ, FUN) do { \
0c942a2017-10-31Arne Goedeke  INT16 _fun_ = (FUN); \
a6d61a2003-04-25Martin Stjernholm  struct object *_=(OBJ); \
a5cf652014-06-24Henrik Grubbström (Grubba)  struct svalue *_sp_ = Pike_sp++; \
a6d61a2003-04-25Martin Stjernholm  debug_malloc_touch(_); \
0c942a2017-10-31Arne Goedeke  SET_SVAL_TYPE_SUBTYPE(*_sp_, PIKE_T_FUNCTION, _fun_); \
a6d61a2003-04-25Martin Stjernholm  _sp_->u.object=_; \ } while (0) #define ref_push_program(P) do{ \ struct program *_=(P); \
379c892003-04-25Martin Stjernholm  struct svalue *_sp_ = Pike_sp++; \
a6d61a2003-04-25Martin Stjernholm  add_ref(_); \
722f712014-06-28Henrik Grubbström (Grubba)  SET_SVAL_TYPE_CHECKER(*_sp_, PIKE_T_PROGRAM); \
a6d61a2003-04-25Martin Stjernholm  _sp_->u.program=_; \ }while(0) #define ref_push_mapping(M) do{ \ struct mapping *_=(M); \
379c892003-04-25Martin Stjernholm  struct svalue *_sp_ = Pike_sp++; \
a6d61a2003-04-25Martin Stjernholm  add_ref(_); \
722f712014-06-28Henrik Grubbström (Grubba)  SET_SVAL_TYPE_CHECKER(*_sp_, PIKE_T_MAPPING); \
a6d61a2003-04-25Martin Stjernholm  _sp_->u.mapping=_; \ }while(0) #define ref_push_array(A) do{ \ struct array *_=(A); \
379c892003-04-25Martin Stjernholm  struct svalue *_sp_ = Pike_sp++; \
a6d61a2003-04-25Martin Stjernholm  add_ref(_); \
722f712014-06-28Henrik Grubbström (Grubba)  SET_SVAL_TYPE_CHECKER(*_sp_, PIKE_T_ARRAY); \
a6d61a2003-04-25Martin Stjernholm  _sp_->u.array=_ ; \ }while(0) #define ref_push_multiset(L) do{ \ struct multiset *_=(L); \
379c892003-04-25Martin Stjernholm  struct svalue *_sp_ = Pike_sp++; \
a6d61a2003-04-25Martin Stjernholm  add_ref(_); \
722f712014-06-28Henrik Grubbström (Grubba)  SET_SVAL_TYPE_CHECKER(*_sp_, PIKE_T_MULTISET); \
a6d61a2003-04-25Martin Stjernholm  _sp_->u.multiset=_; \ }while(0) #define ref_push_string(S) do{ \ struct pike_string *_=(S); \
a5cf652014-06-24Henrik Grubbström (Grubba)  struct svalue *_sp_ = Pike_sp++; \
1714452003-12-23Henrik Grubbström (Grubba)  DO_IF_DEBUG(if(_->size_shift & ~3) { \ Pike_fatal("Pushing string with bad shift: %d\n", \ _->size_shift); \ }); \
a6d61a2003-04-25Martin Stjernholm  add_ref(_); \
7666f82014-06-19Per Hedbor  SET_SVAL_TYPE_SUBTYPE(*_sp_, PIKE_T_STRING,0); \
a6d61a2003-04-25Martin Stjernholm  _sp_->u.string=_; \ }while(0) #define ref_push_type_value(S) do{ \ struct pike_type *_=(S); \
a5cf652014-06-24Henrik Grubbström (Grubba)  struct svalue *_sp_ = Pike_sp++; \
a6d61a2003-04-25Martin Stjernholm  add_ref(_); \
7666f82014-06-19Per Hedbor  SET_SVAL_TYPE_SUBTYPE(*_sp_, PIKE_T_TYPE,0); \
a6d61a2003-04-25Martin Stjernholm  _sp_->u.type=_; \ }while(0)
2d12341997-03-10Fredrik Hübinette (Hubbe) 
7666f82014-06-19Per Hedbor #define ref_push_object(O) ref_push_object_inherit(O,0)
f69fe52004-12-18Henrik Grubbström (Grubba)  #define ref_push_object_inherit(O, INH_NUM) do{ \
0c942a2017-10-31Arne Goedeke  INT16 _inherit_ = (INH_NUM); \
f69fe52004-12-18Henrik Grubbström (Grubba)  struct object *_ = (O); \
a5cf652014-06-24Henrik Grubbström (Grubba)  struct svalue *_sp_ = Pike_sp++; \
f69fe52004-12-18Henrik Grubbström (Grubba)  add_ref(_); \
0c942a2017-10-31Arne Goedeke  SET_SVAL_TYPE_SUBTYPE(*_sp_, PIKE_T_OBJECT, _inherit_); \
f69fe52004-12-18Henrik Grubbström (Grubba)  _sp_->u.object = _; \
a6d61a2003-04-25Martin Stjernholm  }while(0) #define ref_push_function(OBJ, FUN) do { \
0c942a2017-10-31Arne Goedeke  INT16 _fun_ = (FUN); \
a6d61a2003-04-25Martin Stjernholm  struct object *_=(OBJ); \
a5cf652014-06-24Henrik Grubbström (Grubba)  struct svalue *_sp_ = Pike_sp++; \
a6d61a2003-04-25Martin Stjernholm  add_ref(_); \
0c942a2017-10-31Arne Goedeke  SET_SVAL_TYPE_SUBTYPE(*_sp_, PIKE_T_FUNCTION, _fun_); \
a6d61a2003-04-25Martin Stjernholm  _sp_->u.object=_; \ } while (0) #define push_svalue(S) do { \ const struct svalue *_=(S); \
0c942a2017-10-31Arne Goedeke  struct svalue *_sp_ = Pike_sp; \
a6d61a2003-04-25Martin Stjernholm  assign_svalue_no_free(_sp_,_); \
0c942a2017-10-31Arne Goedeke  Pike_sp = _sp_ + 1; \
a6d61a2003-04-25Martin Stjernholm  }while(0)
5267b71995-08-09Fredrik Hübinette (Hubbe) 
a2ad152000-02-16Fredrik Hübinette (Hubbe) #define stack_dup() push_svalue(Pike_sp-1)
a6d61a2003-04-25Martin Stjernholm  #define stack_swap() do { \ struct svalue *_sp_ = Pike_sp; \ struct svalue _=_sp_[-1]; \ _sp_[-1]=_sp_[-2]; \ _sp_[-2]=_; \ } while(0)
3635bb1998-02-19Fredrik Hübinette (Hubbe) 
8b54e92014-08-26Stephen R. van den Berg #define stack_revroll(args) do { \ struct svalue *_sp_ = Pike_sp; \ int _args_ = (args); struct svalue _=_sp_[-1]; \ memmove(_sp_-_args_+1, _sp_-_args_, (_args_-1)*sizeof(struct svalue)); \ _sp_[-_args_]=_; \ } while(0)
7666f82014-06-19Per Hedbor #if PIKE_T_INT+NUMBER_NUMBER==0 && defined(HAS___BUILTIN_MEMSET) #define push_zeroes(N) do{ \ ptrdiff_t num_ = (N); \ __builtin_memset(Pike_sp,0,sizeof(struct svalue)*(num_)); \ Pike_sp+=num_; \ } while(0); #else
b23b112001-08-15Fredrik Hübinette (Hubbe) #define push_zeroes(N) do{ \
a5cf652014-06-24Henrik Grubbström (Grubba)  struct svalue *s_ = Pike_sp; \
b23b112001-08-15Fredrik Hübinette (Hubbe)  ptrdiff_t num_= (N); \ for(;num_-- > 0;s_++) \ { \
7666f82014-06-19Per Hedbor  SET_SVAL_TYPE_SUBTYPE(*s_, PIKE_T_INT,NUMBER_NUMBER); \
b23b112001-08-15Fredrik Hübinette (Hubbe)  s_->u.integer=0; \ } \ Pike_sp=s_; \ }while(0)
7666f82014-06-19Per Hedbor #endif
b23b112001-08-15Fredrik Hübinette (Hubbe)  #define push_undefines(N) do{ \
a5cf652014-06-24Henrik Grubbström (Grubba)  struct svalue *s_ = Pike_sp; \
b23b112001-08-15Fredrik Hübinette (Hubbe)  ptrdiff_t num_= (N); \ for(;num_-- > 0;s_++) \ { \
7666f82014-06-19Per Hedbor  SET_SVAL_TYPE_SUBTYPE(*s_, PIKE_T_INT,NUMBER_UNDEFINED); \
b23b112001-08-15Fredrik Hübinette (Hubbe)  s_->u.integer=0; \ } \ Pike_sp=s_; \ }while(0)
711b072001-03-08Fredrik Hübinette (Hubbe) 
6417722013-06-12Per Hedbor 
50ea682003-03-14Henrik Grubbström (Grubba) #define free_pike_frame(F) do{ struct pike_frame *f_=(F); if(!sub_ref(f_)) really_free_pike_frame(f_); }while(0)
4218011999-01-31Fredrik Hübinette (Hubbe) 
fa21262001-08-31Fredrik Hübinette (Hubbe) /* A scope is any frame which may have malloced locals */
50ea682003-03-14Henrik Grubbström (Grubba) #define free_pike_scope(F) do{ struct pike_frame *f_=(F); if(!sub_ref(f_)) really_free_pike_scope(f_); }while(0)
fa21262001-08-31Fredrik Hübinette (Hubbe) 
a79f462013-10-20Henrik Grubbström (Grubba) #define ASSIGN_CURRENT_STORAGE(VAR, TYPE, INH, EXPECTED_PROGRAM) \ do { \ int inh__ = (INH); \ DO_IF_DEBUG( \ struct program *prog__ = (EXPECTED_PROGRAM); \ if ((inh__ < 0) || \ (inh__ >= Pike_fp->context->prog->num_inherits)) \ Pike_fatal("Inherit #%d out of range [0..%d]\n", \ inh__, Pike_fp->context->prog->num_inherits-1); \ if (prog__ && (Pike_fp->context[inh__].prog != prog__)) \ Pike_fatal("Inherit #%d has wrong program %p != %p.\n", \ Pike_fp->context[inh__].prog, prog__); \ ); \ VAR = ((TYPE *)(Pike_fp->current_object->storage + \ Pike_fp->context[inh__].storage_offset)); \ } while(0)
3635bb1998-02-19Fredrik Hübinette (Hubbe) 
b1f4eb1998-01-13Fredrik Hübinette (Hubbe) enum apply_type { APPLY_STACK, /* The function is the first argument */ APPLY_SVALUE, /* arg1 points to an svalue containing the function */
24c37f2001-05-24Fredrik Hübinette (Hubbe)  APPLY_SVALUE_STRICT, /* Like APPLY_SVALUE, but does not return values for void functions */
7666f82014-06-19Per Hedbor  APPLY_LOW /* arg1 is the object pointer,(int)arg2 the function */
b1f4eb1998-01-13Fredrik Hübinette (Hubbe) };
5267b71995-08-09Fredrik Hübinette (Hubbe) #define APPLY_MASTER(FUN,ARGS) \ do{ \
10f7cc2018-02-16Mateusz Krawczuk  const char* _fun_ = (FUN); \ int _args_ = (ARGS); \ static int id_, master_cnt=0; \
5267b71995-08-09Fredrik Hübinette (Hubbe)  struct object *master_ob=master(); \ if(master_cnt != master_ob->prog->id) \ { \
10f7cc2018-02-16Mateusz Krawczuk  id_=find_identifier(_fun_,master_ob->prog); \
5267b71995-08-09Fredrik Hübinette (Hubbe)  master_cnt = master_ob->prog->id; \ } \
10f7cc2018-02-16Mateusz Krawczuk  if (id_ >= 0) { \ apply_low(master_ob, id_, _args_); \
6deaa32006-03-17Henrik Grubbström (Grubba)  } else { \
10f7cc2018-02-16Mateusz Krawczuk  Pike_error("Cannot call undefined function \"%s\" in master.\n", _fun_); \
6deaa32006-03-17Henrik Grubbström (Grubba)  } \
5267b71995-08-09Fredrik Hübinette (Hubbe) }while(0) #define SAFE_APPLY_MASTER(FUN,ARGS) \ do{ \
10f7cc2018-02-16Mateusz Krawczuk  const char* _fun_ = (FUN); \ int _args_ = (ARGS); \ static int id_, master_cnt=0; \
5267b71995-08-09Fredrik Hübinette (Hubbe)  struct object *master_ob=master(); \ if(master_cnt != master_ob->prog->id) \ { \
10f7cc2018-02-16Mateusz Krawczuk  id_=find_identifier(_fun_,master_ob->prog); \
5267b71995-08-09Fredrik Hübinette (Hubbe)  master_cnt = master_ob->prog->id; \ } \
10f7cc2018-02-16Mateusz Krawczuk  safe_apply_low2(master_ob, id_, _args_, _fun_); \
5267b71995-08-09Fredrik Hübinette (Hubbe) }while(0)
8fa6b52001-06-08Henrik Grubbström (Grubba) #define SAFE_APPLY_HANDLER(FUN, HANDLER, COMPAT, ARGS) do { \ static int h_fun_=-1, h_id_=0; \ static int c_fun_=-1, c_fun_id_=0; \ struct object *h_=(HANDLER), *c_=(COMPAT); \
b5e5382001-06-11Henrik Grubbström (Grubba)  if (h_ && h_->prog) { \
8fa6b52001-06-08Henrik Grubbström (Grubba)  if (h_->prog->id != h_id_) { \ h_fun_ = find_identifier(fun, h_->prog); \ h_id_ = h_->prog->id; \ } \ if (h_fun_ != -1) { \ safe_apply_low(h_, h_fun_, ARGS); \ break; \ } \ } \
b5e5382001-06-11Henrik Grubbström (Grubba)  if (c_ && c_->prog) { \
8fa6b52001-06-08Henrik Grubbström (Grubba)  if (c_->prog->id != c_id_) { \ c_fun_ = find_identifier(fun, c_->prog); \ c_id_ = c_->prog->id; \ } \ if (c_fun_ != -1) { \ safe_apply_low(c_, c_fun_, ARGS); \ break; \ } \ } \ SAFE_APPLY_MASTER(FUN, ARGS); \ } while(0)
032a812001-08-18Fredrik Hübinette (Hubbe) 
0f65e12002-09-14Martin Stjernholm #ifdef INTERNAL_PROFILING PMOD_EXPORT extern unsigned long evaluator_callback_calls; #endif
85155d2010-03-24Martin Stjernholm #define low_check_threads_etc() do { \
0f65e12002-09-14Martin Stjernholm  DO_IF_INTERNAL_PROFILING (evaluator_callback_calls++); \
d2361e2003-06-30Martin Stjernholm  call_callback(& evaluator_callbacks, NULL); \
13670c2015-05-25Martin Nilsson }while(0)
0a861b1997-09-17Fredrik Hübinette (Hubbe) 
85155d2010-03-24Martin Stjernholm #define check_threads_etc() do { \ DO_IF_DEBUG (if (Pike_interpreter.trace_level > 2) \ fprintf (stderr, "- thread yield point\n")); \ low_check_threads_etc(); \ } while (0)
51d7d82008-11-18Martin Stjernholm extern int fast_check_threads_counter;
c846981997-10-13Fredrik Hübinette (Hubbe) 
51d7d82008-11-18Martin Stjernholm #define fast_check_threads_etc(X) do { \
85155d2010-03-24Martin Stjernholm  DO_IF_DEBUG (if (Pike_interpreter.trace_level > 2) \ fprintf (stderr, "- thread yield point\n")); \
51d7d82008-11-18Martin Stjernholm  if (++fast_check_threads_counter >= (1 << (X))) { \ fast_check_threads_counter = 0; \
85155d2010-03-24Martin Stjernholm  low_check_threads_etc(); \
51d7d82008-11-18Martin Stjernholm  } \ } while(0) /* Used before any sort of pike level function call. This covers most * code paths. An interval with magnitude 6 on a 2 GHz AMD 64 averages * on 1000-3000 check_threads_etc calls per second in mixed code, but * it can vary greatly - from 0 to 30000+ calls/sec. In a test case * with about 22000 calls/sec, it took 0.042% of the cpu. */
d442492008-11-19Martin Stjernholm #define FAST_CHECK_THREADS_ON_CALL() do { \
85155d2010-03-24Martin Stjernholm  DO_IF_DEBUG (if (Pike_interpreter.trace_level > 2) \ fprintf (stderr, "- thread yield point\n")); \
d442492008-11-19Martin Stjernholm  if (++fast_check_threads_counter >= (1 << 6)) { \ fast_check_threads_counter = 0; \
85155d2010-03-24Martin Stjernholm  low_check_threads_etc(); \
d442492008-11-19Martin Stjernholm  } \ else if (objects_to_destruct) \ /* De facto pike semantics requires that freed objects are */ \ /* destructed before function calls. Otherwise done through */ \ /* evaluator_callbacks. */ \ destruct_objects_to_destruct_cb(); \ } while (0)
51d7d82008-11-18Martin Stjernholm  /* Used before any sort of backward branch. This is only a safeguard * for some corner cases with loops without calls - not relevant in * ordinary code. */ #define FAST_CHECK_THREADS_ON_BRANCH() fast_check_threads_etc (8)
0a861b1997-09-17Fredrik Hübinette (Hubbe) 
5267b71995-08-09Fredrik Hübinette (Hubbe) /* Prototypes begin here */
be478c1997-08-30Henrik Grubbström (Grubba) void push_sp_mark(void);
45705c2000-08-09Henrik Grubbström (Grubba) ptrdiff_t pop_sp_mark(void);
cc2e9f2003-09-24Martin Stjernholm void gc_mark_stack_external (struct pike_frame *frame, struct svalue *stack_p, struct svalue *stack);
d97eb72011-07-10Henrik Grubbström (Grubba) PMOD_EXPORT int low_init_interpreter(struct Pike_interpreter_struct *interpreter);
4ee9222000-12-13Fredrik Hübinette (Hubbe) PMOD_EXPORT void init_interpreter(void);
52f3d72015-02-08Henrik Grubbström (Grubba) int lvalue_to_svalue_no_free(struct svalue *to, struct svalue *lval);
4ee9222000-12-13Fredrik Hübinette (Hubbe) PMOD_EXPORT void assign_lvalue(struct svalue *lval,struct svalue *from);
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT union anything *get_pointer_if_this_type(struct svalue *lval, TYPE_T t);
be478c1997-08-30Henrik Grubbström (Grubba) void print_return_value(void); void reset_evaluator(void);
bf10442015-04-30Martin Nilsson #ifdef PIKE_DEBUG
5267b71995-08-09Fredrik Hübinette (Hubbe) struct backlog;
bf10442015-04-30Martin Nilsson PMOD_EXPORT void dump_backlog(void); #endif /* PIKE_DEBUG */
cc08512013-06-12Per Hedbor struct catch_context *alloc_catch_context(void); PMOD_EXPORT void really_free_catch_context( struct catch_context *data ); PMOD_EXPORT void really_free_pike_frame( struct pike_frame *X ); void count_memory_in_catch_contexts(size_t*, size_t*); void count_memory_in_pike_frames(size_t*, size_t*); /*BLOCK_ALLOC (catch_context, 0);*/ /*BLOCK_ALLOC(pike_frame,128);*/
4218011999-01-31Fredrik Hübinette (Hubbe) 
142b002003-11-25Martin Stjernholm #ifdef PIKE_USE_MACHINE_CODE
3b54e52014-08-21Martin Nilsson void call_check_threads_etc(void);
8434c22003-12-09Henrik Grubbström (Grubba) #if defined(OPCODE_INLINE_BRANCH) || defined(INS_F_JUMP) || \ defined(INS_F_JUMP_WITH_ARG) || defined(INS_F_JUMP_WITH_TWO_ARGS)
3b54e52014-08-21Martin Nilsson void branch_check_threads_etc(void);
142b002003-11-25Martin Stjernholm #endif
4555f32011-05-11Henrik Grubbström (Grubba) #ifdef OPCODE_INLINE_RETURN
55e9462011-05-16Henrik Grubbström (Grubba) PIKE_OPCODE_T *inter_return_opcode_F_CATCH(PIKE_OPCODE_T *addr);
4555f32011-05-11Henrik Grubbström (Grubba) #endif
26da462017-02-21Martin Karlgren #ifdef OPCODE_INLINE_CATCH PIKE_OPCODE_T *setup_catch_context(PIKE_OPCODE_T *addr); PIKE_OPCODE_T *handle_caught_exception(void); #endif
142b002003-11-25Martin Stjernholm #ifdef PIKE_DEBUG
b1f6a62003-03-21Martin Stjernholm void simple_debug_instr_prologue_0 (PIKE_INSTR_T instr); void simple_debug_instr_prologue_1 (PIKE_INSTR_T instr, INT32 arg); void simple_debug_instr_prologue_2 (PIKE_INSTR_T instr, INT32 arg1, INT32 arg2);
31984c2003-03-20Martin Stjernholm #endif
142b002003-11-25Martin Stjernholm #endif /* PIKE_USE_MACHINE_CODE */
31984c2003-03-20Martin Stjernholm 
342fef2000-08-23Fredrik Hübinette (Hubbe) PMOD_EXPORT void find_external_context(struct external_variable_context *loc, int arg2);
cc08512013-06-12Per Hedbor struct pike_frame *alloc_pike_frame(void);
291e3e2018-03-30Tobias S. Josefowitz void LOW_POP_PIKE_FRAME_slow_path(struct pike_frame *frame);
e29cb72001-09-01Henrik Grubbström (Grubba) void really_free_pike_scope(struct pike_frame *scope);
5909f92013-08-15Per Hedbor void *lower_mega_apply( INT32 args, struct object *o, ptrdiff_t fun ); void *low_mega_apply(enum apply_type type, INT32 args, void *arg1, void *arg2);
9ddbf22001-05-10Fredrik Hübinette (Hubbe) void low_return(void);
2ac9502001-08-14Fredrik Hübinette (Hubbe) void low_return_pop(void);
9ddbf22001-05-10Fredrik Hübinette (Hubbe) void unlink_previous_frame(void);
70fbc12011-05-02Per Hedbor int apply_low_safe_and_stupid(struct object *o, INT32 offset);
ba43672011-11-05Bill Welliver PMOD_EXPORT struct Pike_interpreter_struct * pike_get_interpreter_pointer();
e68c782006-07-05Martin Stjernholm PMOD_EXPORT void mega_apply(enum apply_type type, INT32 args, void *arg1, void *arg2);
6417722013-06-12Per Hedbor PMOD_EXPORT void mega_apply_low(INT32 args, void *arg1, ptrdiff_t arg2);
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void f_call_function(INT32 args);
6697042000-11-20Martin Stjernholm PMOD_EXPORT void call_handle_error(void);
ef8d2a2008-04-14Henrik Grubbström (Grubba) PMOD_EXPORT int safe_apply_low(struct object *o,int fun,int args); PMOD_EXPORT int safe_apply_low2(struct object *o,int fun,int args,
c4accf2006-03-17Henrik Grubbström (Grubba)  const char *fun_name);
ef8d2a2008-04-14Henrik Grubbström (Grubba) PMOD_EXPORT int safe_apply(struct object *o, const char *fun ,INT32 args);
70fbc12011-05-02Per Hedbor int low_unsafe_apply_handler(const char *fun,
61863e2001-12-20Martin Stjernholm  struct object *handler, struct object *compat, INT32 args);
70fbc12011-05-02Per Hedbor void low_safe_apply_handler(const char *fun,
9036e82001-08-16Martin Stjernholm  struct object *handler, struct object *compat, INT32 args); PMOD_EXPORT int safe_apply_handler(const char *fun, struct object *handler, struct object *compat, INT32 args, TYPE_FIELD rettypes);
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void apply_lfun(struct object *o, int fun, int args); PMOD_EXPORT void apply_shared(struct object *o,
06983f1996-09-22Fredrik Hübinette (Hubbe)  struct pike_string *fun,
5267b71995-08-09Fredrik Hübinette (Hubbe)  int args);
a641292014-11-06Martin Nilsson PMOD_EXPORT void apply(struct object *o, const char *fun, int args);
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void apply_svalue(struct svalue *s, INT32 args);
6026c62004-09-22Martin Stjernholm PMOD_EXPORT void safe_apply_svalue (struct svalue *s, INT32 args, int handle_errors);
9335ea2003-01-17Henrik Grubbström (Grubba) PMOD_EXPORT void apply_external(int depth, int fun, INT32 args);
70fbc12011-05-02Per Hedbor void slow_check_stack(void);
66a1572001-01-12Martin Stjernholm PMOD_EXPORT void custom_check_stack(ptrdiff_t amount, const char *fmt, ...)
c915472000-12-04Martin Stjernholm  ATTRIBUTE((format (printf, 2, 3)));
4ee9222000-12-13Fredrik Hübinette (Hubbe) PMOD_EXPORT void cleanup_interpret(void);
d97eb72011-07-10Henrik Grubbström (Grubba) PMOD_EXPORT void low_cleanup_interpret(struct Pike_interpreter_struct *interpreter);
b660c81999-03-01Fredrik Hübinette (Hubbe) void really_clean_up_interpret(void);
5267b71995-08-09Fredrik Hübinette (Hubbe) /* Prototypes end here */
d080fb2000-08-07Henrik Grubbström (Grubba) #define apply_low(O,FUN,ARGS) \
6417722013-06-12Per Hedbor  mega_apply_low((ARGS), (void*)(O),(FUN))
d080fb2000-08-07Henrik Grubbström (Grubba)  #define strict_apply_svalue(SVAL,ARGS) \ mega_apply(APPLY_SVALUE, (ARGS), (void*)(SVAL),0)
114b162003-01-18Henrik Grubbström (Grubba) #define apply_current(FUN, ARGS) \ apply_low(Pike_fp->current_object, \
fa93a52008-02-28Henrik Grubbström (Grubba)  (FUN) + Pike_fp->context->identifier_level, \
114b162003-01-18Henrik Grubbström (Grubba)  (ARGS))
4931982008-04-14Henrik Grubbström (Grubba) #define safe_apply_current(FUN, ARGS) \ safe_apply_low(Pike_fp->current_object, \ (FUN) + Pike_fp->context->identifier_level, \ (ARGS))
9648962008-04-20Henrik Grubbström (Grubba) #define safe_apply_current2(FUN, ARGS, FUNNAME) \ safe_apply_low2(Pike_fp->current_object, \ (FUN) + Pike_fp->context->identifier_level, \ (ARGS), (FUNNAME))
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT extern int Pike_stack_size;
70fbc12011-05-02Per Hedbor struct callback;
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT extern struct callback_list evaluator_callbacks;
e132001998-11-19Fredrik Hübinette (Hubbe) 
8a26932014-07-21Per Hedbor PMOD_EXPORT extern struct Pike_interpreter_struct *
1d16162014-08-25Per Hedbor #if defined(__GNUC__) && __GNUC__ >= 3 __restrict
8a26932014-07-21Per Hedbor #endif Pike_interpreter_pointer;
d97eb72011-07-10Henrik Grubbström (Grubba) #define Pike_interpreter (*Pike_interpreter_pointer)
5923b12000-07-06Fredrik Hübinette (Hubbe)  #define Pike_sp Pike_interpreter.stack_pointer #define Pike_fp Pike_interpreter.frame_pointer
17f08c2000-07-06Fredrik Hübinette (Hubbe) #define Pike_mark_sp Pike_interpreter.mark_stack_pointer
e132001998-11-19Fredrik Hübinette (Hubbe) 
a2ad152000-02-16Fredrik Hübinette (Hubbe) 
60d9872000-03-23Fredrik Hübinette (Hubbe) #define CURRENT_STORAGE (dmalloc_touch(struct pike_frame *,Pike_fp)->current_storage)
24c37f2001-05-24Fredrik Hübinette (Hubbe)  #define PIKE_STACK_MMAPPED struct Pike_stack { struct svalue *top; int flags; struct Pike_stack *previous; struct svalue *save_ptr; struct svalue stack[1]; }; #define PIKE_STACK_REQUIRE_BEGIN(num, base) do { \
4061442001-05-25Henrik Grubbström (Grubba)  struct Pike_stack *old_stack_; \
24c37f2001-05-24Fredrik Hübinette (Hubbe)  if(Pike_interpreter.current_stack->top - Pike_sp < num) \ { \
4061442001-05-25Henrik Grubbström (Grubba)  old_stack_=Pike_interpreter.current_stack; \ old_stack_->save_ptr=Pike_sp; \
24c37f2001-05-24Fredrik Hübinette (Hubbe)  Pike_interpreter.current_stack=allocate_array(MAXIMUM(num, 8192)); \
4061442001-05-25Henrik Grubbström (Grubba)  while(old_sp > base) *(Pike_sp++) = *--old_stack_->save_ptr; \
24c37f2001-05-24Fredrik Hübinette (Hubbe)  } #define PIKE_STACK_REQUIRE_END() \ while(Pike_sp > Pike_interpreter.current_stack->stack) \
4061442001-05-25Henrik Grubbström (Grubba)  *(old_stack_->save_ptr++) = *--Pike_sp; \
24c37f2001-05-24Fredrik Hübinette (Hubbe)  Pike_interpreter.current_stack=Pike_interpreter.current_stack->previous; \
13670c2015-05-25Martin Nilsson }while(0)
24c37f2001-05-24Fredrik Hübinette (Hubbe) 
291e3e2018-03-30Tobias S. Josefowitz 
ea3e9e2018-03-30Arne Goedeke /* Without fancy accounting stuff. This one can't assume there is an * identifier corresponding to the frame (i.e. _fp_->ident might be * bogus). */ PIKE_UNUSED_ATTRIBUTE
291e3e2018-03-30Tobias S. Josefowitz static inline void LOW_POP_PIKE_FRAME(struct pike_frame *frame) { struct pike_frame *tmp = frame->next; if (LIKELY(!sub_ref(frame))) really_free_pike_frame(frame); else LOW_POP_PIKE_FRAME_slow_path(frame); Pike_fp = tmp;
ea3e9e2018-03-30Arne Goedeke } PIKE_UNUSED_ATTRIBUTE static inline void POP_PIKE_FRAME(void) {
291e3e2018-03-30Tobias S. Josefowitz  struct pike_frame *frame = Pike_fp;
0cce512018-03-30Arne Goedeke #ifdef PROFILING /* Time spent in this frame + children. */ cpu_time_t time_passed = get_cpu_time() - Pike_interpreter.unlocked_time; /* Time spent in children to this frame. */ cpu_time_t time_in_children; /* Time spent in just this frame. */ cpu_time_t self_time; struct identifier *function; W_PROFILING_DEBUG("%p}: Pop got %" PRINT_CPU_TIME " (%" PRINT_CPU_TIME ")" " %" PRINT_CPU_TIME " (%" PRINT_CPU_TIME ")n", Pike_interpreter.thread_state, time_passed,
291e3e2018-03-30Tobias S. Josefowitz  frame->start_time,
0cce512018-03-30Arne Goedeke  Pike_interpreter.accounted_time,
291e3e2018-03-30Tobias S. Josefowitz  frame->children_base); time_passed -= frame->start_time;
0cce512018-03-30Arne Goedeke # ifdef PIKE_DEBUG if (time_passed < 0) { Pike_fatal("Negative time_passed: %" PRINT_CPU_TIME " now: %" PRINT_CPU_TIME " unlocked_time: %" PRINT_CPU_TIME " start_time: %" PRINT_CPU_TIME "n", time_passed, get_cpu_time(), Pike_interpreter.unlocked_time,
291e3e2018-03-30Tobias S. Josefowitz  frame->start_time);
0cce512018-03-30Arne Goedeke  } # endif /* PIKE_DEBUG */
291e3e2018-03-30Tobias S. Josefowitz  time_in_children = Pike_interpreter.accounted_time - frame->children_base;
0cce512018-03-30Arne Goedeke # ifdef PIKE_DEBUG if (time_in_children < 0) { Pike_fatal("Negative time_in_children: %" PRINT_CPU_TIME " accounted_time: %" PRINT_CPU_TIME " children_base: %" PRINT_CPU_TIME "n", time_in_children, Pike_interpreter.accounted_time,
291e3e2018-03-30Tobias S. Josefowitz  frame->children_base);
0cce512018-03-30Arne Goedeke  } # endif /* PIKE_DEBUG */ self_time = time_passed - time_in_children; # ifdef PIKE_DEBUG if (self_time < 0) { Pike_fatal("Negative self_time: %" PRINT_CPU_TIME " time_passed: %" PRINT_CPU_TIME " time_in_children: %" PRINT_CPU_TIME "n", self_time, time_passed, time_in_children); } # endif /* PIKE_DEBUG */ Pike_interpreter.accounted_time += self_time; /* FIXME: Can context->prog be NULL? */
291e3e2018-03-30Tobias S. Josefowitz  function = frame->context->prog->identifiers + frame->ident;
0cce512018-03-30Arne Goedeke  if (!--function->recur_depth) function->total_time += time_passed; function->self_time += self_time; #endif /* PROFILING */
291e3e2018-03-30Tobias S. Josefowitz  LOW_POP_PIKE_FRAME (frame);
ea3e9e2018-03-30Arne Goedeke }
5267b71995-08-09Fredrik Hübinette (Hubbe) #endif