pike.git/
src/
interpret.c
Branch:
Tag:
Non-build tags
All tags
No tags
2017-11-18
2017-11-18 10:13:13 by Arne Goedeke <el@laramies.com>
f006ed2f4c81ce2fb35f109eb4c997ea9a338bd3 (
303
lines) (+
302
/-
1
)
[
Show
|
Annotate
]
Branch:
arne/faster_calls_again
Interpreter: de-inline apply_low.h
2405:
} apply_low:
-
#
include
"apply
_
low
.
h
"
+
{
+
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:
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;
+
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;
+
}
+
/* 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);
+
+
/* 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);
+
}
+
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) {