pike.git / src / interpret.c

version» Context lines:

pike.git/src/interpret.c:3548:    c->ptr = s->u.program;    break;    case T_OBJECT:    callsite_resolve_lfun(c, s->u.object, LFUN_CALL);    return;    }    if (PIKE_NEEDS_TRACE())    callsite_trace_call_svalue(c, s);   }    + static void pike_pop_locals(struct svalue *save_sp, ptrdiff_t n) { +  struct svalue *sp = Pike_sp; +  ptrdiff_t pop = sp - save_sp - n; +  +  if (!pop) return; +  +  free_svalues(save_sp, pop, T_MIXED); +  Pike_sp -= pop; +  +  if (n) memmove(save_sp, save_sp+pop, n*sizeof(struct svalue)); +  +  low_destruct_objects_to_destruct(); + } +    PMOD_EXPORT void callsite_reset_pikecall(struct pike_callsite *c) {    struct pike_frame *frame;      #ifdef PIKE_DEBUG    if (c->type != CALLTYPE_PIKEFUN)    Pike_fatal("Calling callsite_reset_pikecall() on non pike frame.\n");   #endif       frame = c->frame;   
pike.git/src/interpret.c:3598:    n->num_args = 0;    n->return_addr = NULL;    if (n->scope) add_ref(n->scope);    add_ref(n->current_object);    add_ref(n->current_program);       LOW_POP_PIKE_FRAME(frame);       c->frame = n;    Pike_fp = n; +  +  /* +  * We pop all 'leftover' locals here, since that +  * was not done in the last call to callsite_return. +  */ +  if (c->retval + c->args < Pike_sp) +  pike_pop_locals(c->retval, c->args);   }      PMOD_EXPORT void callsite_execute(const struct pike_callsite *c) {    FAST_CHECK_THREADS_ON_CALL();    switch (c->type) {    default:    case CALLTYPE_NONE:   #ifdef PIKE_DEBUG    Pike_fatal("Unknown callsite type: %d\n", c->type);   #endif
pike.git/src/interpret.c:3660: Inside #if defined(PIKE_DEBUG)
   if (c->type != CALLTYPE_PIKEFUN)    Pike_fatal("callsite_save_jmpbuf called for non pike frame.\n");   #endif       c->saved_jmpbuf = Pike_interpreter.catching_eval_jmpbuf;    SET_ONERROR (c->onerror, restore_catching_eval_jmpbuf, c->saved_jmpbuf);    Pike_interpreter.catching_eval_jmpbuf = NULL;   }      PMOD_EXPORT void callsite_free_frame(struct pike_callsite *c) { +  struct pike_frame *frame = c->frame; +  INT32 refs; +    #ifdef PIKE_DEBUG -  if (!c->frame) +  if (!frame)    Pike_fatal("callsite_free_frame called without frame.\n");   #endif       /* FREE FRAME */       if (c->type == CALLTYPE_PIKEFUN) -  Pike_mark_sp=Pike_fp->save_mark_sp; -  POP_PIKE_FRAME(); +  Pike_mark_sp=frame->save_mark_sp;    -  +  refs = frame->refs; +  +  LOW_POP_PIKE_FRAME(frame); +  +  /* If the frame had more than 1 reference, no +  * locals were poped, yet. +  */ +  if (UNLIKELY(refs > 1)) { +  ptrdiff_t needs_retval = !(frame->flags & PIKE_FRAME_RETURN_POP); +  +  if (c->retval + needs_retval < Pike_sp) +  pike_pop_locals(c->retval, needs_retval); +  } +     if (c->type != CALLTYPE_PIKEFUN) return;       /* restore catching_eval_jmpbuf */       Pike_interpreter.catching_eval_jmpbuf = c->saved_jmpbuf;    UNSET_ONERROR(c->onerror);   }      PMOD_EXPORT void callsite_return_slowpath(struct pike_callsite *c) {    const struct svalue *sp = Pike_sp; -  struct svalue *retval = c->retval; +  struct svalue *save_sp = c->retval;    struct pike_frame *frame = c->frame; -  int got_retval = 1; -  int pop = 0; +  ptrdiff_t needs_retval = (c->type != CALLTYPE_PIKEFUN || !(frame->flags & PIKE_FRAME_RETURN_POP));    -  /* NOTE: this is necessary because of recursion */ -  if (c->type == CALLTYPE_PIKEFUN) { -  pop = frame->flags & PIKE_FRAME_RETURN_POP; -  } -  +    #ifdef PIKE_DEBUG    if(Pike_mark_sp < Pike_fp->save_mark_sp)    Pike_fatal("Popped below save_mark_sp!\n");    if(Pike_sp<Pike_interpreter.evaluator_stack)    Pike_fatal("Stack error (also simple).\n");   #endif    -  if (retval >= sp) { +  if (save_sp >= sp) {   #ifdef PIKE_DEBUG -  if (retval - sp > 1) +  if (save_sp - sp > 1)    Pike_fatal("Stack too small after function call.\n");   #endif    /* return value missing */ -  if (!(c->flags & CALL_NEED_NO_RETVAL) && !pop) { +  if (!(c->flags & CALL_NEED_NO_RETVAL) && needs_retval) {    push_int(0); -  } else got_retval = 0; -  } else if (retval+1 < sp) { -  /* garbage left on the stack */ -  if (pop) -  pop_n_elems(sp-retval); -  else -  stack_pop_n_elems_keep_top (sp - retval - 1); -  low_destruct_objects_to_destruct(); +     } -  +  } else if ((!frame || frame->refs == 1)) { +  /* +  * some locals left on the stack. We can pop them here +  * if the frame has one reference, only. Otherwise +  * they will either be popped in callsite_reset or callsite_free +  */ +  if (save_sp + needs_retval < sp) +  pike_pop_locals(save_sp, needs_retval); +  }       if (PIKE_NEEDS_TRACE())    callsite_trace_return(c);   }      ATTRIBUTE((noinline))   static void callsite_trace_call_fun(const struct pike_callsite *c) {    struct object *o = Pike_fp->current_object;    struct identifier *function = ID_FROM_INT (o->prog, Pike_fp->fun);