pike.git / src / interpret.c

version» Context lines:

pike.git/src/interpret.c:25:   #include "signal_handler.h"   #include "gc.h"   #include "threads.h"   #include "callback.h"   #include "fd_control.h"   #include "pike_security.h"   #include "bignum.h"   #include "pike_types.h"   #include "pikecode.h"    - #include "block_alloc.h" -  +    #include <fcntl.h>   #include <errno.h>   #include <ctype.h>      #ifdef HAVE_MMAP   #ifdef HAVE_SYS_TYPES_H   #include <sys/types.h>   #endif      #ifdef HAVE_SYS_MMAN_H
pike.git/src/interpret.c:1092:    }while(e!=backlogp);   }      #else /* PIKE_DEBUG */      #define DEBUG_LOG_ARG(arg) 0   #define DEBUG_LOG_ARG2(arg2) 0      #endif /* !PIKE_DEBUG */    - #undef BLOCK_ALLOC_NEXT - #define BLOCK_ALLOC_NEXT prev +     - BLOCK_ALLOC_FILL_PAGES (catch_context, 1) -  - #define POP_CATCH_CONTEXT do { \ -  struct catch_context *cc = Pike_interpreter.catch_ctx; \ -  DO_IF_DEBUG ( \ -  TRACE((3,"- Popping catch context %p ==> %p\n", \ -  cc, cc ? cc->prev : NULL)); \ -  if (!Pike_interpreter.catching_eval_jmpbuf) \ -  Pike_fatal ("Not in catching eval.\n"); \ -  if (!cc) \ -  Pike_fatal ("Catch context dropoff.\n"); \ -  if (cc->frame != Pike_fp) \ -  Pike_fatal ("Catch context doesn't belong to this frame.\n"); \ + #define POP_CATCH_CONTEXT do { \ +  struct catch_context *cc = Pike_interpreter.catch_ctx; \ +  DO_IF_DEBUG ( \ +  TRACE((3,"- Popping catch context %p ==> %p\n", \ +  cc, cc ? cc->prev : NULL)); \ +  if (!Pike_interpreter.catching_eval_jmpbuf) \ +  Pike_fatal ("Not in catching eval.\n"); \ +  if (!cc) \ +  Pike_fatal ("Catch context dropoff.\n"); \ +  if (cc->frame != Pike_fp) \ +  Pike_fatal ("Catch context doesn't belong to this frame.\n"); \    if (Pike_mark_sp != cc->recovery.mark_sp + Pike_interpreter.mark_stack) \ -  Pike_fatal ("Mark sp diff in catch context pop.\n"); \ -  ); \ -  debug_malloc_touch (cc); \ -  UNSETJMP (cc->recovery); \ -  Pike_fp->expendible = cc->save_expendible; \ -  Pike_interpreter.catch_ctx = cc->prev; \ -  really_free_catch_context (cc); \ +  Pike_fatal ("Mark sp diff in catch context pop.\n"); \ +  ); \ +  debug_malloc_touch (cc); \ +  UNSETJMP (cc->recovery); \ +  Pike_fp->expendible = cc->save_expendible; \ +  Pike_interpreter.catch_ctx = cc->prev; \ +  really_free_catch_context (cc); \    } while (0)    -  + static struct catch_context *free_catch_context; + static int num_catch_ctx, num_free_catch_ctx; +  + PMOD_EXPORT void really_free_catch_context( struct catch_context *data ) + { +  if( num_free_catch_ctx > 100 && free_catch_context ) +  { +  num_catch_ctx--; +  free( data ); +  } +  else +  { +  data->prev = free_catch_context; +  num_free_catch_ctx++; +  free_catch_context = data; +  } + } +  + struct catch_context *alloc_catch_context(void) + { +  struct catch_context *res; +  if( free_catch_context ) +  { +  num_free_catch_ctx--; +  res = free_catch_context; +  free_catch_context = res->prev; +  } +  else +  { +  num_catch_ctx++; +  res = xalloc( sizeof( struct catch_context ) ); +  } +  return res; + } +  + void count_memory_in_catch_contexts(size_t *num, size_t *size ) + { +  *num = (num_catch_ctx-num_free_catch_ctx); +  *size = num_catch_ctx * (sizeof(struct catch_context)+8); /* assumes 8 bytes overhead. */ + } +  + static void free_all_catch_context_blocks(void) + { +  struct catch_context *x = free_catch_context, *n; +  while( x ) +  { +  n = x->prev; +  free( x ); +  x = n; +  } +  free_catch_context = NULL; + } +    static int catching_eval_instruction (PIKE_OPCODE_T *pc);         #ifdef PIKE_USE_MACHINE_CODE   #ifdef OPCODE_INLINE_RETURN   /* Catch notes:    *    * Typical F_CATCH use:    *    * F_CATCH
pike.git/src/interpret.c:1877:    SNPRINTF(buf, sizeof (buf), "%s:", file);    fprintf(stderr,"- %-20s %s\n",buf,s);    }       if (filep) {    free_string(filep);    }    free(s);   }    + static struct pike_frame *free_pike_frame; + static struct pike_frame_chunk { +  struct pike_frame_chunk *next; + } *pike_frame_chunks; + static int num_pike_frame_chunks; + static int num_pike_frames;    - #undef BLOCK_ALLOC_NEXT - #define BLOCK_ALLOC_NEXT next + PMOD_EXPORT void really_free_pike_frame( struct pike_frame *X ) + { +  free_object(X->current_object); +  if(X->current_program) +  free_program(X->current_program); +  if(X->scope) +  free_pike_scope(X->scope); +  DO_IF_SECURITY( if(X->current_creds) free_object(X->current_creds) ); +  DO_IF_DEBUG( +  if(X->flags & PIKE_FRAME_MALLOCED_LOCALS) +  Pike_fatal("Pike frame is not supposed to have malloced locals here!\n")); +  DO_IF_DMALLOC( +  X->current_program=0; +  X->context=0; +  X->scope=0; +  X->current_object=0; +  X->flags=0; +  X->expendible=0; +  X->locals=0; +  DO_IF_SECURITY( X->current_creds=0; ) +  ); +  X->next = free_pike_frame; +  free_pike_frame = X; + }    - #undef INIT_BLOCK - #define INIT_BLOCK(X) do { \ -  X->refs=0; \ -  add_ref(X); /* For DMALLOC... */ \ -  X->flags=0; \ -  X->scope=0; \ -  DO_IF_SECURITY( if(CURRENT_CREDS) { \ -  add_ref(X->current_creds=CURRENT_CREDS); \ -  } else { \ -  X->current_creds = 0; \ -  }) \ - }while(0) + struct pike_frame *alloc_pike_frame(void) + { +  struct pike_frame *res; +  if( free_pike_frame ) +  { +  res = free_pike_frame; +  free_pike_frame = res->next; +  res->refs=0; +  add_ref(res); /* For DMALLOC... */ +  res->flags=0; +  res->next=0; +  res->scope=0;    - #undef EXIT_BLOCK - #define EXIT_BLOCK(X) do { \ -  free_object(X->current_object); \ -  if(X->current_program) free_program(X->current_program); \ -  if(X->scope) free_pike_scope(X->scope); \ -  DO_IF_SECURITY( if(X->current_creds) { \ -  free_object(X->current_creds); \ -  }) \ -  DO_IF_DEBUG( \ -  if(X->flags & PIKE_FRAME_MALLOCED_LOCALS) \ -  Pike_fatal("Pike frame is not supposed to have malloced locals here!\n")); \ -  \ -  DO_IF_DMALLOC( \ -  X->current_program=0; \ -  X->context=0; \ -  X->scope=0; \ -  X->current_object=0; \ -  X->flags=0; \ -  X->expendible=0; \ -  X->locals=0; \ -  DO_IF_SECURITY( X->current_creds=0; ) \ -  ) \ - }while(0) +  DO_IF_SECURITY( +  if(CURRENT_CREDS) { +  add_ref(res->current_creds=CURRENT_CREDS); +  } else { +  res->current_creds = 0; +  });    - BLOCK_ALLOC_FILL_PAGES(pike_frame, 4) +  return res; +  }    -  +  /* Need to allocate more. */ +  { +  unsigned int i; + #define FRAMES_PER_CHUNK ((4096*4-8-sizeof(struct pike_frame_chunk))/sizeof(struct catch_context)) + #define FRAME_CHUNK_SIZE (FRAMES_PER_CHUNK*sizeof(struct catch_context))+sizeof(struct pike_frame_chunk)    -  +  void *p = xalloc( FRAME_CHUNK_SIZE ); +  num_pike_frame_chunks++; +  ((struct pike_frame_chunk*)p)->next = pike_frame_chunks; +  pike_frame_chunks = p; +  free_pike_frame = res = (struct pike_frame*)((char*)p+sizeof(struct pike_frame_chunk)); +  for( i=1; i<FRAMES_PER_CHUNK; i++ ) +  { +  res->next = &free_pike_frame[i]; +  res = res->next; +  } +  res->next = NULL; +  num_pike_frames+=FRAMES_PER_CHUNK; +  } +  return alloc_pike_frame(); + } +  + void count_memory_in_pike_frames(size_t *num, size_t *size ) + { +  *num = num_pike_frames; +  *size = num_pike_frame_chunks * (FRAME_CHUNK_SIZE*8); + } + #undef FRAMES_PER_CHUNK + #undef FRAME_CHUNK_SIZE +  + static void free_all_pike_frame_blocks(void) + { +  struct pike_frame_chunk *x = pike_frame_chunks, *n; +  while( x ) +  { +  n = x->next; +  free(x); +  x = n; +  } +  free_pike_frame = NULL; +  pike_frame_chunks = NULL; +  num_pike_frames=0; +  num_pike_frame_chunks=0; + } +    void really_free_pike_scope(struct pike_frame *scope)   {    if(scope->flags & PIKE_FRAME_MALLOCED_LOCALS)    {    free_mixed_svalues(scope->locals,scope->num_locals);    free((char *)(scope->locals));   #ifdef PIKE_DEBUG    scope->flags&=~PIKE_FRAME_MALLOCED_LOCALS;   #endif    }    really_free_pike_frame(scope);   }    -  + int lower_mega_apply( INT32 args, struct object *o, ptrdiff_t fun ) + { +  struct program *p; +  check_stack(256); +  check_mark_stack(256); +  +  if( (p = o->prog) ) +  { +  struct svalue *save_sp = Pike_sp - args; +  struct reference *ref = p->identifier_references + fun; +  struct inherit *context = p->inherits + ref->inherit_offset; +  struct identifier *function = context->prog->identifiers + ref->identifier_offset; +  struct svalue *constant = NULL; +  struct pike_frame *new_frame = NULL; +  +  int type = (function->identifier_flags & (IDENTIFIER_TYPE_MASK|IDENTIFIER_ALIAS)); +  if( o->prog != pike_trampoline_program && function->func.offset != -1 ) +  { +  switch( type ) +  { +  case IDENTIFIER_CONSTANT: +  constant = &context->prog->constants[function->func.const_info.offset].sval; +  if( TYPEOF(*constant) != PIKE_T_PROGRAM ) +  break; +  case IDENTIFIER_C_FUNCTION: +  case IDENTIFIER_PIKE_FUNCTION: +  if( !new_frame ) +  { +  new_frame=alloc_pike_frame(); +  debug_malloc_touch(new_frame); +  } + #ifdef PROFILING +  new_frame->children_base = Pike_interpreter.accounted_time; +  new_frame->start_time = get_cpu_time() - Pike_interpreter.unlocked_time; +  +  /* This is mostly for profiling, but +  * could also be used to find out the name of a function +  * in a destructed object. -hubbe +  * +  * Since it not used for anything but profiling yet, I will +  * put it here until someone needs it. -Hubbe +  */ +  new_frame->ident = ref->identifier_offset; +  DO_IF_PROFILING_DEBUG({ +  fprintf(stderr, "%p{: Push at %" PRINT_CPU_TIME +  " %" PRINT_CPU_TIME "\n", +  Pike_interpreter.thread_state, new_frame->start_time, +  new_frame->children_base); +  }); + #endif +  new_frame->next = Pike_fp; +  add_ref(new_frame->current_object = o); +  add_ref(new_frame->current_program = p); +  new_frame->context = context; +  new_frame->fun = DO_NOT_WARN((unsigned INT16)fun); +  new_frame->expendible = new_frame->locals = save_sp; +  new_frame->args = args; +  new_frame->save_sp = save_sp; +  + #ifdef PIKE_DEBUG +  if (Pike_in_gc > GC_PASS_PREPARE && Pike_in_gc < GC_PASS_FREE) +  Pike_fatal("Pike code called within gc.\n"); + #endif +  +  Pike_fp = new_frame; +  debug_malloc_touch(Pike_fp); + #ifdef PROFILING +  function->num_calls++; +  function->recur_depth++; + #endif + #ifdef PIKE_USE_MACHINE_CODE +  call_check_threads_etc(); + #endif +  +  if( !constant ) +  { +  if (PIKE_FN_START_ENABLED()) +  { +  /* DTrace enter probe +  arg0: function name +  arg1: object +  */ +  dynamic_buffer save_buf; +  dynbuf_string obj_name; +  struct svalue obj_sval; +  SET_SVAL(obj_sval, T_OBJECT, 0, object, o); +  init_buf(&save_buf); +  safe_describe_svalue(&obj_sval, 0, NULL); +  obj_name = complex_free_buf(&save_buf); +  PIKE_FN_START(function->name->size_shift == 0 ? +  function->name->str : "[widestring fn name]", +  obj_name.str); +  } +  if(UNLIKELY(Pike_interpreter.trace_level)) +  { +  dynamic_buffer save_buf; +  char buf[50]; +  +  init_buf(&save_buf); +  sprintf(buf, "%lx->", DO_NOT_WARN((long) PTR_TO_INT (o))); +  my_strcat(buf); +  if (function->name->size_shift) +  my_strcat ("[widestring function name]"); +  else +  my_strcat(function->name->str); +  do_trace_call(args, &save_buf); +  } +  if( type == IDENTIFIER_C_FUNCTION ) +  { +  new_frame->num_args = args; +  new_frame->num_locals = args; +  new_frame->current_storage = o->storage+context->storage_offset; +  new_frame->pc = 0; +  (*function->func.c_fun)(args); +  +  /* .. and below follows what is basically a copy of the +  * low_return function... +  */ +  if(save_sp+1 > Pike_sp) +  { +  push_int(0); +  } else if(save_sp+1 < Pike_sp) { +  stack_pop_n_elems_keep_top( Pike_sp-save_sp-1 ); +  } +  if(UNLIKELY(Pike_interpreter.trace_level>1)) +  do_trace_func_return (1, o, fun); +  goto pop; +  } +  new_frame->save_mark_sp=new_frame->mark_sp_base=Pike_mark_sp; +  new_frame->pc = new_frame->context->prog->program + function->func.offset + #ifdef ENTRY_PROLOGUE_SIZE +  + ENTRY_PROLOGUE_SIZE + #endif /* ENTRY_PROLOGUE_SIZE */ +  ; +  return 1; +  } +  else +  { +  struct object *tmp; +  tmp=parent_clone_object(constant->u.program, +  o, +  fun, +  args); +  push_object(tmp); +  pop: +  POP_PIKE_FRAME(); +  return 0; +  } +  } +  } +  } +  return low_mega_apply( APPLY_LOW, args, o, (void*)fun ); + } +    /* Apply a function.    *    * Application types:    *    * APPLY_STACK: Apply Pike_sp[-args] with args-1 arguments.    *    * APPLY_SVALUE: Apply the svalue at arg1, and adjust the stack    * to leave a return value.    *    * APPLY_SVALUE_STRICT: Apply the svalue at arg1, and don't adjust the
pike.git/src/interpret.c:2073: Inside #if defined(PIKE_DEBUG)
   if(Pike_sp==expected_stack+1 && s->u.efun->may_return_void)    Pike_fatal("Void function returned with a value on the stack: %S %d\n",    s->u.efun->name, s->u.efun->may_return_void);    }   #endif       break;    }else{    type=APPLY_SVALUE;    o=s->u.object; +  fun = SUBTYPEOF(*s);    if(o->prog == pike_trampoline_program && -  SUBTYPEOF(*s) == QUICK_FIND_LFUN(pike_trampoline_program, LFUN_CALL)) +  fun == QUICK_FIND_LFUN(pike_trampoline_program, LFUN_CALL))    {    fun=((struct pike_trampoline *)(o->storage))->func;    scope=((struct pike_trampoline *)(o->storage))->frame;    o=scope->current_object; -  goto apply_low_with_scope; +     } -  fun = SUBTYPEOF(*s); +     goto apply_low;    }    break;       case T_ARRAY:    if(Pike_interpreter.trace_level)    {    dynamic_buffer save_buf;    init_buf(&save_buf);    safe_describe_svalue(s,0,0);
pike.git/src/interpret.c:2143:    break;       case T_OBJECT:    /* FIXME: Object subtypes! */    o=s->u.object;    if(o->prog == pike_trampoline_program)    {    fun=((struct pike_trampoline *)(o->storage))->func;    scope=((struct pike_trampoline *)(o->storage))->frame;    o=scope->current_object; -  goto apply_low_with_scope; +  goto apply_low;    }    fun=LFUN_CALL;    type=APPLY_SVALUE;    goto call_lfun;    }    break;    }       call_lfun: {    int lfun;
pike.git/src/interpret.c:2176:       case APPLY_LOW:    o = (struct object *)arg1;    fun = PTR_TO_INT(arg2);    if(o->prog == pike_trampoline_program &&    fun == QUICK_FIND_LFUN(pike_trampoline_program, LFUN_CALL))    {    fun=((struct pike_trampoline *)(o->storage))->func;    scope=((struct pike_trampoline *)(o->storage))->frame;    o=scope->current_object; -  goto apply_low_with_scope; +     }       apply_low: - #undef SCOPE +    #include "apply_low.h"    break; -  -  apply_low_with_scope: - #define SCOPE scope - #include "apply_low.h" -  break; +     }       if(save_sp+1 > Pike_sp)    {    if(type != APPLY_SVALUE_STRICT) {    push_int(0);    if(Pike_interpreter.trace_level>1)    do_trace_func_return (1, o, fun);    }    else    if(Pike_interpreter.trace_level>1)    do_trace_func_return (0, o, fun);    }else{    if(save_sp+1 < Pike_sp)    {    assign_svalue(save_sp,Pike_sp-1);    pop_n_elems(Pike_sp-save_sp-1);    low_destruct_objects_to_destruct(); /* consider using a flag for immediate destruct instead... */ -  +     }    if(Pike_interpreter.trace_level>1)    do_trace_func_return (1, o, fun);    }       if (PIKE_FN_DONE_ENABLED()) {    /* DTrace leave probe    arg0: function name    */    char *fn = "(unknown)";
pike.git/src/interpret.c:2244:    Pike_fatal("Stack error (also simple).\n"); \    ) \    \    Pike_mark_sp=Pike_fp->save_mark_sp; \    \    POP_PIKE_FRAME()         void low_return(void)   { -  struct svalue *save_sp = Pike_fp->save_sp; -  int trace_level = Pike_interpreter.trace_level; -  struct object *o; /* Got bogus gcc warning here. */ -  int fun; /* Got bogus gcc warning here. */ +  struct svalue *save_sp = Pike_fp->save_sp+1; +  struct object *o = Pike_fp->current_object; +  int fun = Pike_fp->fun;    -  if (trace_level > 1) { -  o = Pike_fp->current_object; -  fun = Pike_fp->fun; -  } -  +     if (PIKE_FN_DONE_ENABLED()) {    /* DTrace leave probe    arg0: function name    */    char *fn = "(unknown)"; -  o = Pike_fp->current_object; -  fun = Pike_fp->fun; +     if (o && o->prog) {    struct identifier *id = ID_FROM_INT(o->prog, fun);    fn = id->name->size_shift == 0 ? id->name->str : "[widestring fn name]";    }    PIKE_FN_DONE(fn);    }      #if defined (PIKE_USE_MACHINE_CODE) && defined (OPCODE_RETURN_JUMPADDR)    /* If the function that returns is the only ref to the current    * object and its program then the program would be freed in    * destruct_objects_to_destruct below. However, we're still    * executing in an opcode in its code so we need prog->program to    * stick around for a little while more to handle the returned    * address. We therefore add a ref to the current object so that    * it'll live through this function. */ -  o = Pike_fp->current_object; +     add_ref (o);   #endif       basic_low_return (save_sp); -  if(save_sp+1 > Pike_sp) -  { -  push_int(0); -  }else{ -  if(save_sp+1 < Pike_sp) -  { -  stack_pop_n_elems_keep_top (Pike_sp - save_sp - 1); +     -  +  stack_pop_n_elems_keep_top (Pike_sp - save_sp); +  {    /* consider using a flag for immediate destruct instead... */ -  +  extern struct object *objects_to_destruct; +  if( objects_to_destruct )    destruct_objects_to_destruct();    } -  } +     -  if(trace_level>1) + #ifdef PIKE_DEBUG +  if(save_sp > Pike_sp) +  Pike_fatal("Pike function did not leave an return value\n"); + #endif +  +  if(UNLIKELY(Pike_interpreter.trace_level>1))    do_trace_func_return (1, o, fun);      #if defined (PIKE_USE_MACHINE_CODE) && defined (OPCODE_RETURN_JUMPADDR)    free_object (o);   #endif   }      void low_return_pop(void)   {    struct svalue *save_sp = Pike_fp->save_sp;
pike.git/src/interpret.c:2327:    int fun = Pike_fp->fun;    if (o && o->prog) {    struct identifier *id = ID_FROM_INT(o->prog, fun);    fn = id->name->size_shift == 0 ? id->name->str : "[widestring fn name]";    }    PIKE_FN_DONE(fn);    }       basic_low_return (save_sp);    -  if(save_sp < Pike_sp) -  { +     pop_n_elems(Pike_sp-save_sp);    /* consider using a flag for immediate destruct instead... */    destruct_objects_to_destruct(); -  } +       #if defined (PIKE_USE_MACHINE_CODE) && defined (OPCODE_RETURN_JUMPADDR)    free_object (o);   #endif   }         void unlink_previous_frame(void)   {    struct pike_frame *current, *prev;
pike.git/src/interpret.c:2366: Inside #if defined(PIKE_DEBUG)
   /* FIXME: Wouldn't a simple return be ok? */    if(rec->frame_pointer == current->next)    Pike_fatal("You can't touch this!\n");    }    }   #endif    /* Save various fields from the previous frame.    */    current->save_sp=prev->save_sp;    current->save_mark_sp=prev->save_mark_sp; -  current->flags=prev->flags; +  current->flags = prev->flags;       /* Unlink the top frame temporarily. */    Pike_interpreter.frame_pointer=prev;      #ifdef PROFILING    {    /* We must update the profiling info of the previous frame    * to account for that the current frame has gone away.    */    cpu_time_t total_time =
pike.git/src/interpret.c:2409:    POP_PIKE_FRAME();       /* Hook our frame again. */    current->next=Pike_interpreter.frame_pointer;    Pike_interpreter.frame_pointer=current;      #ifdef PROFILING    current->children_base = Pike_interpreter.accounted_time;    current->start_time = get_cpu_time() - Pike_interpreter.unlocked_time;   #endif /* PROFILING */ -  - #if 0 -  /* FIXME: This code is questionable, and the Pike_sp -  * adjustment ought to modify the mark stack. -  */ -  { -  int freespace; -  /* Move svalues down */ -  freespace=current->locals - current->save_sp; -  if(freespace > ((Pike_sp - current->locals)<<2) + 32) -  { -  assign_svalues(current->save_sp, -  current->locals, -  Pike_sp - current->locals, -  BIT_MIXED); -  -  current->locals-=freespace; -  current->expendible-=freespace; -  pop_n_elems(freespace); +    }    -  /* Move pointers down */ -  freespace=current->mark_sp_base - current->save_mark_sp; -  if(freespace > ((Pike_mark_sp - current->mark_sp_base)<<2)+32) -  { -  MEMMOVE(current->save_mark_sp, -  current->mark_sp_base, -  sizeof(struct svalue **)*(Pike_mark_sp - current->mark_sp_base)); -  current->mark_sp_base-=freespace; -  Pike_mark_sp-=freespace; -  } -  } - #endif /* 0 */ - } -  +    static void restore_catching_eval_jmpbuf (LOW_JMP_BUF *p)   {    Pike_interpreter.catching_eval_jmpbuf = p;   }      PMOD_EXPORT void mega_apply(enum apply_type type, INT32 args, void *arg1, void *arg2)   {    /* Save and clear Pike_interpreter.catching_eval_jmpbuf so that the    * following eval_instruction will install a LOW_JMP_BUF of its    * own to handle catches. */    LOW_JMP_BUF *saved_jmpbuf = Pike_interpreter.catching_eval_jmpbuf;    ONERROR uwp;    Pike_interpreter.catching_eval_jmpbuf = NULL;    SET_ONERROR (uwp, restore_catching_eval_jmpbuf, saved_jmpbuf);       /* The C stack margin is normally 8 kb, but if we get here during a    * lowered margin then don't fail just because of that, unless it's    * practically zero. */    check_c_stack(Pike_interpreter.c_stack_margin ?    Pike_interpreter.c_stack_margin : 100); -  +  if( low_mega_apply(type, args, arg1, arg2) ) +  { +  eval_instruction(Pike_fp->pc + #ifdef ENTRY_PROLOGUE_SIZE +  - ENTRY_PROLOGUE_SIZE + #endif /* ENTRY_PROLOGUE_SIZE */ +  ); +  low_return(); +  } +  CALL_AND_UNSET_ONERROR(uwp); + }    -  if(low_mega_apply(type, args, arg1, arg2)) + PMOD_EXPORT void mega_apply_low(INT32 args, void *arg1, ptrdiff_t arg2)   { -  +  /* Save and clear Pike_interpreter.catching_eval_jmpbuf so that the +  * following eval_instruction will install a LOW_JMP_BUF of its +  * own to handle catches. */ +  LOW_JMP_BUF *saved_jmpbuf = Pike_interpreter.catching_eval_jmpbuf; +  ONERROR uwp; +  Pike_interpreter.catching_eval_jmpbuf = NULL; +  SET_ONERROR (uwp, restore_catching_eval_jmpbuf, saved_jmpbuf); +  +  /* The C stack margin is normally 8 kb, but if we get here during a +  * lowered margin then don't fail just because of that, unless it's +  * practically zero. */ +  check_c_stack(Pike_interpreter.c_stack_margin ? +  Pike_interpreter.c_stack_margin : 100); +  if( lower_mega_apply( args, arg1, arg2 ) ) +  {    eval_instruction(Pike_fp->pc   #ifdef ENTRY_PROLOGUE_SIZE    - ENTRY_PROLOGUE_SIZE   #endif /* ENTRY_PROLOGUE_SIZE */    );    low_return();    }    CALL_AND_UNSET_ONERROR(uwp);   }   
pike.git/src/interpret.c:2600:    mark_free_svalue (&throw_value);    }   }      /* NOTE: This function may only be called from the compiler! */   int apply_low_safe_and_stupid(struct object *o, INT32 offset)   {    JMP_BUF tmp;    struct pike_frame *new_frame=alloc_pike_frame();    int ret; -  int use_dummy_reference = 1; +  volatile int use_dummy_reference = 1;    struct program *prog = o->prog;    int p_flags = prog->flags;    LOW_JMP_BUF *saved_jmpbuf;    int fun = -1;       /* Search for a function that belongs to the current program,    * since this is needed for opcodes that use INHERIT_FROM_*    * (eg F_EXTERN) to work.    */    for (fun = prog->num_identifier_references; fun--;) {