pike.git / src / interpret.c

version» Context lines:

pike.git/src/interpret.c:2112:    }    really_free_pike_frame(scope);   }      void *lower_mega_apply( INT32 args, struct object *o, ptrdiff_t fun )   {    struct pike_callsite C;    callsite_init(&C);    callsite_set_args(&C, args);    callsite_resolve_fun(&C, o, fun); -  if (C.type == CALLTYPE_PIKEFUN) return C.ptr; +  if (C.type == CALLTYPE_PIKEFUN) { +  FAST_CHECK_THREADS_ON_CALL(); +  return C.ptr; +  }    /* This is only needed for pike functions right now:    * callsite_prepare(&C); */    callsite_execute(&C);    callsite_return(&C);    callsite_free(&C);    return NULL;   }      /* Apply a function.    *
pike.git/src/interpret.c:2146:    *    * Returns zero if the function was invalid or has been executed.    *    * Returns one if a frame has been set up to start the function    * with eval_instruction(Pike_fp->pc - ENTRY_PROLOGUE_SIZE). After    * eval_instruction() is done the frame needs to be removed by a call    * to low_return().    */   void* low_mega_apply(enum apply_type type, INT32 args, void *arg1, void *arg2)   { -  struct object *o = NULL; -  struct pike_frame *scope=0; -  ptrdiff_t fun=0; -  struct svalue *save_sp=Pike_sp-args; +  struct pike_callsite C;    - #if defined(PIKE_DEBUG) && defined(_REENTRANT) -  if(d_flag) -  { -  THREAD_T self = th_self(); +  callsite_init(&C); +  callsite_set_args(&C, args);    -  CHECK_INTERPRETER_LOCK(); -  -  if (Pike_interpreter.thread_state) { -  if (!th_equal(Pike_interpreter.thread_state->id, self)) -  Pike_fatal("Current thread is wrong.\n"); -  -  DEBUG_CHECK_THREAD(); -  } -  } - #endif -  -  switch(type) -  { +  switch (type) {    case APPLY_STACK: -  if(!args) -  PIKE_ERROR("`()", "Too few arguments (apply stack).\n", Pike_sp, 0); -  args--; -  arg1=(void *)(Pike_sp-args-1); -  -  /* FALL_THROUGH */ -  -  case APPLY_SVALUE: +  C.args--; +  callsite_resolve_svalue(&C, Pike_sp - args); +  break;    case APPLY_SVALUE_STRICT: -  apply_svalue: -  { -  struct svalue *s=(struct svalue *)arg1; -  switch(TYPEOF(*s)) -  { -  case T_INT: -  if (!s->u.integer) { -  PIKE_ERROR("0", "Attempt to call the NULL-value\n", Pike_sp, args); -  } else { -  Pike_error("Attempt to call the value %"PRINTPIKEINT"d\n", -  s->u.integer); -  } +  C.flags |= CALL_NEED_NO_RETVAL; +  case APPLY_SVALUE: +  callsite_resolve_svalue(&C, arg1);    break; -  -  case T_STRING: -  if (s->u.string->len > 20) { -  Pike_error("Attempt to call the string \"%20S\"...\n", s->u.string); -  } else { -  Pike_error("Attempt to call the string \"%S\"\n", s->u.string); -  } -  break; -  -  case T_MAPPING: -  Pike_error("Attempt to call a mapping\n"); -  break; -  -  default: -  Pike_error("Call to non-function value type:%s.\n", -  get_name_of_type(TYPEOF(*s))); -  break; -  -  case T_FUNCTION: -  if(SUBTYPEOF(*s) == FUNCTION_BUILTIN) -  { - #ifdef PIKE_DEBUG -  struct svalue *expected_stack = Pike_sp-args; - #endif -  if(Pike_interpreter.trace_level>1) -  { -  do_trace_efun_call(s, args); -  } -  if (PIKE_FN_START_ENABLED()) { -  do_dtrace_efun_call(s, args); -  } -  FAST_CHECK_THREADS_ON_CALL(); -  (*(s->u.efun->function))(args); -  if (PIKE_FN_DONE_ENABLED()) { -  do_dtrace_efun_return(s, args); -  } -  - #ifdef PIKE_DEBUG -  s->u.efun->runs++; -  if(Pike_sp != expected_stack + !s->u.efun->may_return_void) -  { -  if(Pike_sp < expected_stack) -  Pike_fatal("Function popped too many arguments: %S\n", -  s->u.efun->name); -  if(Pike_sp>expected_stack+1) -  Pike_fatal("Function left droppings on stack: %S\n", -  s->u.efun->name); -  if(Pike_sp == expected_stack && !s->u.efun->may_return_void) -  Pike_fatal("Non-void function returned without return value on stack: %S %d\n", -  s->u.efun->name, s->u.efun->may_return_void); -  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 && -  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; -  } -  break; -  -  case T_ARRAY: -  if(Pike_interpreter.trace_level) -  { -  do_trace_svalue_call(s, args); -  } -  if (PIKE_FN_START_ENABLED()) { -  /* DTrace enter probe -  arg0: function name -  arg1: object -  */ -  PIKE_FN_START("[array]", ""); -  } -  apply_array(s->u.array, args, (type == APPLY_STACK)); -  break; -  -  case PIKE_T_TYPE: -  if (args != 1) { -  /* FIXME: Casts to object ought to propagate to apply program below. */ -  SIMPLE_WRONG_NUM_ARGS_ERROR("cast", 1); -  } -  o_cast(s->u.type, compile_type_to_runtime_type(s->u.type)); -  break; -  -  case T_PROGRAM: -  if(Pike_interpreter.trace_level) -  { -  do_trace_svalue_call(s, args); -  } -  if (PIKE_FN_START_ENABLED()) { -  /* DTrace enter probe -  arg0: function name -  arg1: object -  */ -  struct byte_buffer buf = BUFFER_INIT(); -  safe_describe_svalue(&buf, s,0,0); -  PIKE_FN_START("[program]", buffer_get_string(&buf)); -  buffer_free(&buf); -  } -  push_object(clone_object(s->u.program,args)); -  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; -  } -  fun=LFUN_CALL; -  type=APPLY_SVALUE; -  goto call_lfun; -  } -  break; -  } -  -  call_lfun: { -  int lfun; - #ifdef PIKE_DEBUG -  if(fun < 0 || fun >= NUM_LFUNS) -  Pike_fatal("Apply lfun on illegal value!\n"); - #endif -  if(!o->prog) -  PIKE_ERROR("destructed object", "Apply on destructed object.\n", Pike_sp, args); -  lfun = FIND_LFUN(o->prog, fun); -  if (lfun < 0) -  Pike_error ("Cannot call undefined lfun %s.\n", lfun_names[fun]); -  fun = lfun; -  goto apply_low; -  } -  +     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; -  } -  -  apply_low: -  { -  struct program *p; -  struct reference *ref; -  struct pike_frame *new_frame; -  struct identifier *function; -  - #ifdef PIKE_DEBUG -  if (fun < 0) -  Pike_fatal ("Invalid function offset: %d.\n", fun); - #endif -  check_stack(256); -  check_mark_stack(256); -  - #ifdef PIKE_DEBUG -  { -  static int counter; -  switch(d_flag) -  { -  case 0: -  case 1: -  case 2: +  Pike_fatal("Deprecated. Use lower_mega_apply instead.\n");    break; -  case 3: -  if(!((counter++ & 7))) -  do_debug(); -  break; -  case 4: -  default: -  do_debug(); +     } -  } - #endif +     -  p=o->prog; -  if(!p) -  PIKE_ERROR("destructed object->function", -  "Cannot call functions in destructed objects.\n", Pike_sp, args); -  -  if(!(p->flags & PROGRAM_PASS_1_DONE) || (p->flags & PROGRAM_AVOID_CHECK)) -  PIKE_ERROR("__empty_program() -> function", -  "Cannot call functions in unfinished objects.\n", Pike_sp, args); -  - #ifdef PIKE_DEBUG -  if(fun>=(int)p->num_identifier_references) -  { -  fprintf(stderr, "Function index out of range. %ld >= %d\n", -  (long)fun, (int)p->num_identifier_references); -  fprintf(stderr,"########Program is:\n"); -  describe(p); -  fprintf(stderr,"########Object is:\n"); -  describe(o); -  Pike_fatal("Function index out of range.\n"); -  } - #endif -  -  ref = p->identifier_references + fun; - #ifdef PIKE_DEBUG -  if(ref->inherit_offset>=p->num_inherits) -  Pike_fatal("Inherit offset out of range in program.\n"); - #endif -  -  /* init a new evaluation pike_frame */ -  new_frame=alloc_pike_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; -  W_PROFILING_DEBUG("%p{: Push at %" PRINT_CPU_TIME -  " %" PRINT_CPU_TIME "\n", -  Pike_interpreter.thread_state, new_frame->start_time, -  new_frame->children_base); - #endif -  debug_malloc_touch(new_frame); -  -  new_frame->next = Pike_fp; -  new_frame->current_object = o; -  new_frame->current_program = p; -  new_frame->context = p->inherits + ref->inherit_offset; -  -  function = new_frame->context->prog->identifiers + ref->identifier_offset; -  new_frame->fun = (unsigned INT16)fun; -  -  - #ifdef PIKE_DEBUG -  if(Pike_interpreter.trace_level > 9) -  { -  fprintf(stderr,"-- ref: inoff=%d idoff=%d flags=%d\n", -  ref->inherit_offset, -  ref->identifier_offset, -  ref->id_flags); -  -  fprintf(stderr,"-- context: prog->id=%d inlev=%d idlev=%d pi=%d po=%d so=%ld name=%s\n", -  new_frame->context->prog->id, -  new_frame->context->inherit_level, -  new_frame->context->identifier_level, -  new_frame->context->parent_identifier, -  new_frame->context->parent_offset, -  (long)new_frame->context->storage_offset, -  new_frame->context->name ? new_frame->context->name->str : "NULL"); -  if(Pike_interpreter.trace_level>19) -  { -  describe(new_frame->context->prog); -  } -  } - #endif -  -  -  new_frame->locals = Pike_sp - args; -  new_frame->expendible_offset = 0; -  new_frame->args = args; -  new_frame->pc = 0; -  new_frame->scope=scope; - #ifdef PIKE_DEBUG -  if(scope && new_frame->fun == scope->fun) -  { -  Pike_fatal("Que? A function cannot be parented by itself!\n"); -  } - #endif -  frame_set_save_sp(new_frame, save_sp); -  -  add_ref(new_frame->current_object); -  add_ref(new_frame->current_program); -  if(new_frame->scope) add_ref(new_frame->scope); - #ifdef PIKE_DEBUG -  if (Pike_fp) { -  -  if (new_frame->locals < Pike_fp->locals) { -  Pike_fatal("New locals below old locals: %p < %p\n", -  new_frame->locals, Pike_fp->locals); -  } -  -  if (d_flag > 1) { -  /* Liberal use of variables for debugger convenience. */ -  size_t i; -  struct svalue *l = Pike_fp->locals; -  for (i = 0; l + i < Pike_sp; i++) -  if (TYPEOF(l[i]) != PIKE_T_FREE) -  debug_check_svalue (l + i); -  } -  } - #endif /* PIKE_DEBUG */ -  -  Pike_fp = new_frame; -  -  if(Pike_interpreter.trace_level) -  { -  do_trace_function_call(o, function, args); -  } -  if (PIKE_FN_START_ENABLED()) { -  do_dtrace_function_call(o, function, args); -  } -  - #ifdef PROFILING -  function->num_calls++; -  function->recur_depth++; - #endif -  -  if(function->func.offset == -1) { -  new_frame->num_args = args; -  generic_error(NULL, Pike_sp, args, -  "Calling undefined function.\n"); -  } -  -  switch(function->identifier_flags & (IDENTIFIER_TYPE_MASK|IDENTIFIER_ALIAS)) -  { -  case IDENTIFIER_C_FUNCTION: -  debug_malloc_touch(Pike_fp); -  Pike_fp->num_args=args; -  new_frame->current_storage = o->storage+new_frame->context->storage_offset; -  new_frame->num_locals=args; +  if (C.type == CALLTYPE_PIKEFUN) {    FAST_CHECK_THREADS_ON_CALL(); -  (*function->func.c_fun)(args); -  break; -  -  case IDENTIFIER_CONSTANT: -  { -  struct svalue *s=&(Pike_fp->context->prog-> -  constants[function->func.const_info.offset].sval); -  debug_malloc_touch(Pike_fp); -  if(TYPEOF(*s) == T_PROGRAM) -  { -  struct object *tmp; -  FAST_CHECK_THREADS_ON_CALL(); -  Pike_fp->num_args=args; -  tmp=parent_clone_object(s->u.program, -  o, -  fun, -  args); -  push_object(tmp); -  break; +  return C.ptr;    } -  /* Fall through */ -  } +     -  case IDENTIFIER_VARIABLE: -  { -  /* FIXME: -  * Use new-style tail-recursion instead -  */ -  debug_malloc_touch(Pike_fp); -  debug_malloc_touch(o); -  if(Pike_sp-save_sp-args<=0) -  { -  /* Create an extra svalue for tail recursion style call */ -  Pike_sp++; -  memmove(Pike_sp-args,Pike_sp-args-1,sizeof(struct svalue)*args); - #ifdef DEBUG_MALLOC -  if (args) { -  int i; -  /* Note: touch the dead svalue too. */ -  for (i=args+2; i > 0; i--) { -  dmalloc_touch_svalue(Pike_sp-i); -  } -  } - #endif /* DEBUG_MALLOC */ -  }else{ -  free_svalue(Pike_sp-args-1); -  } -  mark_free_svalue (Pike_sp - args - 1); -  low_object_index_no_free(Pike_sp-args-1,o,fun); +  callsite_execute(&C); +  callsite_return(&C); +  callsite_free(&C);    -  /* No profiling code for calling variables - Hubbe */ -  POP_PIKE_FRAME(); -  -  if(Pike_sp-save_sp-args > (args<<2) + 32) -  { -  /* The test above assures these two areas -  * are not overlapping -  */ -  assign_svalues(save_sp, Pike_sp-args, args, BIT_MIXED); -  pop_n_elems(Pike_sp-save_sp-args); +  return NULL;   } -  arg1=(void *)(Pike_sp-args-1); -  if (PIKE_FN_POPFRAME_ENABLED()) { -  /* DTrace adjust frame depth */ -  PIKE_FN_POPFRAME(); -  } -  goto apply_svalue; -  } +     -  case IDENTIFIER_PIKE_FUNCTION: -  { -  int num_args; -  int num_locals; -  PIKE_OPCODE_T *pc; -  FAST_CHECK_THREADS_ON_CALL(); +     - #ifdef PIKE_DEBUG -  if (Pike_in_gc > GC_PASS_PREPARE && Pike_in_gc < GC_PASS_FREE) -  Pike_fatal("Pike code called within gc.\n"); -  new_frame->num_args = 0; -  new_frame->num_locals = 0; - #endif +     -  debug_malloc_touch(Pike_fp); -  new_frame->current_storage = o->storage+new_frame->context->storage_offset; -  pc=new_frame->context->prog->program + function->func.offset; -  -  new_frame->save_mark_sp=Pike_mark_sp; -  new_frame->pc = pc - #ifdef ENTRY_PROLOGUE_SIZE -  + ENTRY_PROLOGUE_SIZE - #endif /* ENTRY_PROLOGUE_SIZE */ -  ; -  -  return new_frame->pc; -  } -  -  default: -  if (IDENTIFIER_IS_ALIAS(function->identifier_flags)) { -  POP_PIKE_FRAME(); -  do { -  struct external_variable_context loc; -  loc.o = o; -  loc.inherit = INHERIT_FROM_INT(p, fun); -  loc.parent_identifier = 0; -  find_external_context(&loc, function->func.ext_ref.depth); -  fun = function->func.ext_ref.id; -  p = (o = loc.o)->prog; -  function = ID_FROM_INT(p, fun); -  } while (IDENTIFIER_IS_ALIAS(function->identifier_flags)); -  if (PIKE_FN_POPFRAME_ENABLED()) { -  /* DTrace adjust frame depth */ -  PIKE_FN_POPFRAME(); -  } -  goto apply_low; -  } - #ifdef PIKE_DEBUG -  Pike_fatal("Unknown identifier type.\n"); - #endif -  } -  POP_PIKE_FRAME(); -  } -  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()) { -  do_dtrace_func_return(o, fun); -  } -  -  return 0; - } -  -  -  +    void low_return(void)   {    struct svalue *save_sp = frame_get_save_sp(Pike_fp);    struct object *o = Pike_fp->current_object;    int fun = Pike_fp->fun;    int pop = Pike_fp->flags & PIKE_FRAME_RETURN_POP;       if (PIKE_FN_DONE_ENABLED()) {    /* DTrace leave probe    arg0: function name