pike.git / src / interpreter.h

version» Context lines:

pike.git/src/interpreter.h:1: + /* + || 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. + */    -  + #undef LOW_GET_ARG + #undef LOW_GET_JUMP + #undef LOW_SKIPJUMP   #undef GET_ARG   #undef GET_ARG2 -  + #undef GET_JUMP + #undef SKIPJUMP + #undef DOJUMP + #undef CASE + #undef BREAK + #undef DONE    - #ifdef PIKE_DEBUG + #undef JUMP_DONE + #define JUMP_DONE DONE    - #define GET_ARG() (backlog[backlogp].arg=(\ -  instr=prefix,\ -  prefix=0,\ -  instr+=EXTRACT_UCHAR(pc++),\ -  (t_flag>3 ? sprintf(trace_buffer,"- Arg = %ld\n",(long)instr),write_to_stderr(trace_buffer,strlen(trace_buffer)) : 0),\ -  instr)) + #ifdef HAVE_COMPUTED_GOTO    - #define GET_ARG2() (backlog[backlogp].arg2=(\ -  instr=prefix2,\ -  prefix2=0,\ -  instr+=EXTRACT_UCHAR(pc++),\ -  (t_flag>3 ? sprintf(trace_buffer,"- Arg2= %ld\n",(long)instr),write_to_stderr(trace_buffer,strlen(trace_buffer)) : 0),\ -  instr)) -  - #else - #define GET_ARG() (instr=prefix,prefix=0,instr+EXTRACT_UCHAR(pc++)) - #define GET_ARG2() (instr=prefix2,prefix2=0,instr+EXTRACT_UCHAR(pc++)) - #endif -  - static int eval_instruction(unsigned char *pc) - { -  unsigned INT32 prefix2=0,instr, prefix=0; -  debug_malloc_touch(Pike_fp); -  while(1) -  { -  Pike_fp->pc = pc; -  instr=EXTRACT_UCHAR(pc++); -  + #define CASE(OP) PIKE_CONCAT(LABEL_,OP): FETCH + #define FETCH (instr = PROG_COUNTER[0])   #ifdef PIKE_DEBUG -  if(d_flag) -  { - #ifdef _REENTRANT -  CHECK_INTERPRETER_LOCK(); -  if(OBJ2THREAD(Pike_interpreter.thread_id)->state.thread_id != Pike_interpreter.thread_id) -  fatal("Arglebargle glop glyf, thread swap problem!\n"); + #define DONE continue + #else /* !PIKE_DEBUG */ + #define DONE do { \ +  Pike_fp->pc = PROG_COUNTER++; \ +  goto *instr; \ +  } while(0)    -  if(d_flag>1 && thread_for_id(th_self()) != Pike_interpreter.thread_id) -  fatal("thread_for_id() (or Pike_interpreter.thread_id) failed in interpreter.h! %p != %p\n",thread_for_id(th_self()),Pike_interpreter.thread_id); - #endif + #endif /* PIKE_DEBUG */    -  Pike_sp[0].type=99; /* an invalid type */ -  Pike_sp[1].type=99; -  Pike_sp[2].type=99; -  Pike_sp[3].type=99; + #define LOW_GET_ARG() ((INT32)(ptrdiff_t)(*(PROG_COUNTER++))) + #define LOW_GET_JUMP() ((INT32)(ptrdiff_t)(*(PROG_COUNTER))) + #define LOW_SKIPJUMP() (instr = (++PROG_COUNTER)[0])    -  if(Pike_sp<Pike_interpreter.evaluator_stack || Pike_mark_sp < Pike_interpreter.mark_stack || Pike_fp->locals>Pike_sp) -  fatal("Stack error (generic) sp=%p/%p mark_sp=%p/%p locals=%p.\n", -  Pike_sp, -  Pike_interpreter.evaluator_stack, -  Pike_mark_sp, -  Pike_interpreter.mark_stack, -  Pike_fp->locals); + #define GET_ARG() LOW_GET_ARG() + #define GET_ARG2() LOW_GET_ARG()    -  if(Pike_mark_sp > Pike_interpreter.mark_stack+Pike_stack_size) -  fatal("Mark Stack error (overflow).\n"); + #else /* !HAVE_COMPUTED_GOTO */    -  + #define CASE(X) case (X)-F_OFFSET: + #define DONE break + #define FETCH    -  if(Pike_mark_sp < Pike_interpreter.mark_stack) -  fatal("Mark Stack error (underflow).\n"); + #define LOW_GET_ARG() ((PROG_COUNTER++)[0]) + #if PIKE_BYTECODE_METHOD == PIKE_BYTECODE_SPARC + #define LOW_GET_JUMP() (PROG_COUNTER[0]) + #define LOW_SKIPJUMP() (++PROG_COUNTER) + #else /* PIKE_BYTECODE_METHOD != PIKE_BYTECODE_SPARC */ + #define LOW_GET_JUMP() EXTRACT_INT(PROG_COUNTER) + #define LOW_SKIPJUMP() (PROG_COUNTER += sizeof(INT32)) + #endif /* PIKE_BYTECODE_METHOD */    -  if(Pike_sp > Pike_interpreter.evaluator_stack+Pike_stack_size) -  fatal("stack error (overflow).\n"); + #ifdef PIKE_DEBUG    -  if(/* Pike_fp->fun>=0 && */ Pike_fp->current_object->prog && -  Pike_fp->locals+Pike_fp->num_locals > Pike_sp) -  fatal("Stack error (stupid!).\n"); + #define GET_ARG() ( \ +  instr=prefix, \ +  prefix=0, \ +  instr += LOW_GET_ARG(), \ +  DEBUG_LOG_ARG (instr), \ +  instr)    -  if(Pike_interpreter.recoveries && Pike_sp-Pike_interpreter.evaluator_stack < Pike_interpreter.recoveries->stack_pointer) -  fatal("Stack error (underflow).\n"); + #define GET_ARG2() ( \ +  instr=prefix2, \ +  prefix2=0, \ +  instr += LOW_GET_ARG(), \ +  DEBUG_LOG_ARG2 (instr), \ +  instr)    -  if(Pike_mark_sp > Pike_interpreter.mark_stack && Pike_mark_sp[-1] > Pike_sp) -  fatal("Stack error (underflow?)\n"); + #else /* !PIKE_DEBUG */    -  if(d_flag > 9) do_debug(); + #define GET_ARG() (instr=prefix,prefix=0,instr+LOW_GET_ARG()) + #define GET_ARG2() (instr=prefix2,prefix2=0,instr+LOW_GET_ARG())    -  backlogp++; -  if(backlogp >= BACKLOG) backlogp=0; + #endif /* PIKE_DEBUG */    -  if(backlog[backlogp].program) -  free_program(backlog[backlogp].program); + #endif /* HAVE_COMPUTED_GOTO */    -  backlog[backlogp].program=Pike_fp->context.prog; -  add_ref(Pike_fp->context.prog); -  backlog[backlogp].instruction=instr; -  backlog[backlogp].pc=pc; -  backlog[backlogp].stack = Pike_sp - Pike_interpreter.evaluator_stack; -  backlog[backlogp].mark_stack = Pike_mark_sp - Pike_interpreter.mark_stack; - #ifdef _REENTRANT -  backlog[backlogp].thread_id=Pike_interpreter.thread_id; + #ifndef STEP_BREAK_LINE + #define STEP_BREAK_LINE   #endif    -  debug_malloc_touch(Pike_fp->current_object); -  switch(d_flag) + static int eval_instruction(PIKE_OPCODE_T *pc)   { -  default: -  case 3: -  check_object(Pike_fp->current_object); - /* break; */ +  PIKE_INSTR_T instr; + #ifdef HAVE_COMPUTED_GOTO +  static void *strap = &&init_strap; +  instr = NULL; + #else /* !HAVE_COMPUTED_GOTO */ +  unsigned INT32 prefix2=0,prefix=0; + #endif /* HAVE_COMPUTED_GOTO */ +  /* Variables that are commonly used by the various opcodes. +  * They are defined here to reduce the size of the stack frame. +  */ +  struct svalue tmp, tmp2; +  struct external_variable_context loc; +  struct program *p; +  struct object *o; +  struct svalue *s; +  DO_IF_DEBUG(dynamic_buffer save_buf);    -  case 2: -  check_object_context(Pike_fp->current_object, -  Pike_fp->context.prog, -  CURRENT_STORAGE); -  case 1: -  case 0: -  break; -  } -  } + #undef LOCAL_VAR + #define LOCAL_VAR(X) /* Local variable defined above. */    -  if(t_flag > 2) + #ifdef HAVE_COMPUTED_GOTO +  goto *strap; +  normal_strap: + #endif /* HAVE_COMPUTED_GOTO */ +  +  debug_malloc_touch(Pike_fp); +  while(1)    { -  char *file, *f; -  INT32 linep; +  INT32 arg1, arg2; +  instr = pc[0]; +  Pike_fp->pc = pc++;    -  file=get_line(pc-1,Pike_fp->context.prog,&linep); -  while((f=STRCHR(file,'/'))) file=f+1; -  fprintf(stderr,"- %s:%4ld:(%lx): %-25s %4ld %4ld\n", -  file,(long)linep, -  DO_NOT_WARN((long)(pc-Pike_fp->context.prog->program-1)), -  get_f_name(instr + F_OFFSET), -  DO_NOT_WARN((long)(Pike_sp-Pike_interpreter.evaluator_stack)), -  DO_NOT_WARN((long)(Pike_mark_sp-Pike_interpreter.mark_stack))); -  } +  STEP_BREAK_LINE    -  if(instr + F_OFFSET < F_MAX_OPCODE) -  ADD_RUNNED(instr + F_OFFSET); + #ifdef PIKE_DEBUG +  if (d_flag || Pike_interpreter.trace_level > 2) +  low_debug_instr_prologue (instr);   #endif    -  + #ifdef HAVE_COMPUTED_GOTO +  goto *instr; + #else /* !HAVE_COMPUTED_GOTO */    switch(instr)    { -  +  /* NOTE: The prefix handling is not needed in computed-goto mode. */    /* Support to allow large arguments */ -  CASE(F_PREFIX_256); prefix+=256; break; -  CASE(F_PREFIX_512); prefix+=512; break; -  CASE(F_PREFIX_768); prefix+=768; break; -  CASE(F_PREFIX_1024); prefix+=1024; break; +  CASE(F_PREFIX_256); prefix+=256; DONE; +  CASE(F_PREFIX_512); prefix+=512; DONE; +  CASE(F_PREFIX_768); prefix+=768; DONE; +  CASE(F_PREFIX_1024); prefix+=1024; DONE;    CASE(F_PREFIX_24BITX256); -  prefix+=EXTRACT_UCHAR(pc++)<<24; +  prefix += (pc++)[0]<<24;    CASE(F_PREFIX_WORDX256); -  prefix+=EXTRACT_UCHAR(pc++)<<16; +  prefix += (pc++)[0]<<16;    CASE(F_PREFIX_CHARX256); -  prefix+=EXTRACT_UCHAR(pc++)<<8; -  break; +  prefix += (pc++)[0]<<8; +  DONE;       /* Support to allow large arguments */ -  CASE(F_PREFIX2_256); prefix2+=256; break; -  CASE(F_PREFIX2_512); prefix2+=512; break; -  CASE(F_PREFIX2_768); prefix2+=768; break; -  CASE(F_PREFIX2_1024); prefix2+=1024; break; +  CASE(F_PREFIX2_256); prefix2+=256; DONE; +  CASE(F_PREFIX2_512); prefix2+=512; DONE; +  CASE(F_PREFIX2_768); prefix2+=768; DONE; +  CASE(F_PREFIX2_1024); prefix2+=1024; DONE;    CASE(F_PREFIX2_24BITX256); -  prefix2+=EXTRACT_UCHAR(pc++)<<24; +  prefix2 += (pc++)[0]<<24;    CASE(F_PREFIX2_WORDX256); -  prefix2+=EXTRACT_UCHAR(pc++)<<16; +  prefix2 += (pc++)[0]<<16;    CASE(F_PREFIX2_CHARX256); -  prefix2+=EXTRACT_UCHAR(pc++)<<8; -  break; +  prefix2 += (pc++)[0]<<8; +  DONE; + #endif /* HAVE_COMPUTED_GOTO */         #define INTERPRETER    - #define OPCODE0(OP,DESC) CASE(OP); { - #define OPCODE1(OP,DESC) CASE(OP); { \ -  INT32 arg1=GET_ARG(); + #define OPCODE0(OP, DESC, FLAGS, CODE) CASE(OP); CODE; DONE + #define OPCODE1(OP, DESC, FLAGS, CODE) CASE(OP); { \ +  arg1=GET_ARG(); \ +  FETCH; \ +  CODE; \ +  } DONE    - #define OPCODE2(OP,DESC) CASE(OP); { \ -  INT32 arg1=GET_ARG(); \ -  INT32 arg2=GET_ARG2(); + #define OPCODE2(OP, DESC, FLAGS, CODE) CASE(OP); { \ +  arg1=GET_ARG(); \ +  arg2=GET_ARG2(); \ +  FETCH; \ +  CODE; \ +  } DONE    -  + #define OPCODE0_ALIAS(OP, DESC, FLAGS, FUN) OPCODE0(OP, DESC, FLAGS, {FUN();}) + #define OPCODE1_ALIAS(OP, DESC, FLAGS, FUN) OPCODE1(OP, DESC, FLAGS, {FUN(arg1);}) + #define OPCODE2_ALIAS(OP, DESC, FLAGS, FUN) OPCODE2(OP, DESC, FLAGS, {FUN(arg1, arg2);})    - #define OPCODE0_TAIL(OP,DESC) CASE(OP); - #define OPCODE1_TAIL(OP,DESC) CASE(OP); - #define OPCODE2_TAIL(OP,DESC) CASE(OP); + #define OPCODE0_TAIL(OP, DESC, FLAGS, CODE) CASE(OP); CODE + #define OPCODE1_TAIL(OP, DESC, FLAGS, CODE) CASE(OP); CODE + #define OPCODE2_TAIL(OP, DESC, FLAGS, CODE) CASE(OP); CODE    - #define OPCODE0_JUMP(OP,DESC) CASE(OP); { - #define OPCODE0_TAILJUMP(OP,DESC) } CASE(OP) {; + #define OPCODE0_JUMP OPCODE0 + #define OPCODE1_JUMP OPCODE1 + #define OPCODE2_JUMP OPCODE2 + #define OPCODE0_TAILJUMP OPCODE0_TAIL + #define OPCODE1_TAILJUMP OPCODE1_TAIL + #define OPCODE2_TAILJUMP OPCODE2_TAIL    -  + #define OPCODE0_RETURN(OP, DESC, FLAGS, CODE) OPCODE0(OP, DESC, FLAGS | I_RETURN, CODE) + #define OPCODE1_RETURN(OP, DESC, FLAGS, CODE) OPCODE1(OP, DESC, FLAGS | I_RETURN, CODE) + #define OPCODE2_RETURN(OP, DESC, FLAGS, CODE) OPCODE2(OP, DESC, FLAGS | I_RETURN, CODE) + #define OPCODE0_TAILRETURN(OP, DESC, FLAGS, CODE) OPCODE0_TAIL(OP, DESC, FLAGS | I_RETURN, CODE) + #define OPCODE1_TAILRETURN(OP, DESC, FLAGS, CODE) OPCODE1_TAIL(OP, DESC, FLAGS | I_RETURN, CODE) + #define OPCODE2_TAILRETURN(OP, DESC, FLAGS, CODE) OPCODE2_TAIL(OP, DESC, FLAGS | I_RETURN, CODE) +  + #define OPCODE0_PTRJUMP(OP, DESC, FLAGS, CODE) CASE(OP); CODE; DONE + #define OPCODE0_TAILPTRJUMP(OP, DESC, FLAGS, CODE) CASE(OP); CODE +    /* These are something of a special case as they    * requires a POINTER stored explicitly after    * the instruction itself.    */ - #define OPCODE1_JUMP(OP,DESC) CASE(OP); { \ -  INT32 arg1=GET_ARG(); \ + #define OPCODE1_PTRJUMP(OP, DESC, FLAGS, CODE) CASE(OP); { \ +  arg1=GET_ARG(); \ +  FETCH; \ +  CODE; \ +  } DONE    - #define OPCODE2_JUMP(OP,DESC) CASE(OP); { \ -  INT32 arg1=GET_ARG(); \ -  INT32 arg2=GET_ARG2(); + #define OPCODE2_PTRJUMP(OP, DESC, FLAGS, CODE) CASE(OP); { \ +  arg1=GET_ARG(); \ +  arg2=GET_ARG2(); \ +  FETCH; \ +  CODE; \ +  } DONE    - #define OPCODE1_TAILJUMP(OP,DESC) } CASE(OP) {; - #define OPCODE2_TAILJUMP(OP,DESC) } CASE(OP) {; + #define OPCODE1_TAILPTRJUMP(OP, DESC, FLAGS, CODE) CASE(OP); CODE + #define OPCODE2_TAILPTRJUMP(OP, DESC, FLAGS, CODE) CASE(OP); CODE    -  + #define OPCODE0_BRANCH OPCODE0_PTRJUMP + #define OPCODE1_BRANCH OPCODE1_PTRJUMP + #define OPCODE2_BRANCH OPCODE2_PTRJUMP + #define OPCODE0_TAILBRANCH OPCODE0_TAILPTRJUMP + #define OPCODE1_TAILBRANCH OPCODE1_TAILPTRJUMP + #define OPCODE2_TAILBRANCH OPCODE2_TAILPTRJUMP    - #define BREAK break; } - #define DONE break -  +    #include "interpret_functions.h"    -  + #ifndef HAVE_COMPUTED_GOTO    default: -  fatal("Strange instruction %ld\n",(long)instr); +  Pike_fatal("Strange instruction %ld\n",(long)instr);    } -  + #endif /* !HAVE_COMPUTED_GOTO */ +  }    -  +  /* NOT_REACHED */ +  + #ifdef HAVE_COMPUTED_GOTO +  + #undef OPCODE0 + #undef OPCODE1 + #undef OPCODE2 + #undef OPCODE0_TAIL + #undef OPCODE1_TAIL + #undef OPCODE2_TAIL + #undef OPCODE0_JUMP + #undef OPCODE1_JUMP + #undef OPCODE2_JUMP + #undef OPCODE0_TAILJUMP + #undef OPCODE1_TAILJUMP + #undef OPCODE2_TAILJUMP + #undef OPCODE0_PTRJUMP + #undef OPCODE1_PTRJUMP + #undef OPCODE2_PTRJUMP + #undef OPCODE0_TAILPTRJUMP + #undef OPCODE1_TAILPTRJUMP + #undef OPCODE2_TAILPTRJUMP + #undef OPCODE0_RETURN + #undef OPCODE1_RETURN + #undef OPCODE2_RETURN + #undef OPCODE0_TAILRETURN + #undef OPCODE1_TAILRETURN + #undef OPCODE2_TAILRETURN + #undef OPCODE0_BRANCH + #undef OPCODE1_BRANCH + #undef OPCODE2_BRANCH + #undef OPCODE0_TAILBRANCH + #undef OPCODE1_TAILBRANCH + #undef OPCODE2_TAILBRANCH +  /* NOTE: No need to redefine these. +  * #undef OPCODE0_ALIAS +  * #undef OPCODE1_ALIAS +  * #undef OPCODE2_ALIAS +  */ + #undef LABEL + #define LABEL(OP) &&PIKE_CONCAT(LABEL_,OP) + #define NULL_LABEL(OP) NULL + #define OPCODE0(OP,DESC) LABEL(OP), + #define OPCODE1(OP,DESC) LABEL(OP), + #define OPCODE2(OP,DESC) LABEL(OP), + #define OPCODE0_TAIL(OP,DESC) LABEL(OP), + #define OPCODE1_TAIL(OP,DESC) LABEL(OP), + #define OPCODE2_TAIL(OP,DESC) LABEL(OP), + #define OPCODE0_PTRJUMP(OP,DESC) LABEL(OP), + #define OPCODE1_PTRJUMP(OP,DESC) LABEL(OP), + #define OPCODE2_PTRJUMP(OP,DESC) LABEL(OP), + #define OPCODE0_TAILPTRJUMP(OP,DESC) LABEL(OP), + #define OPCODE1_TAILPTRJUMP(OP,DESC) LABEL(OP), + #define OPCODE2_TAILPTRJUMP(OP,DESC) LABEL(OP), + #define OPCODE0_RETURN(OP,DESC) LABEL(OP), + #define OPCODE1_RETURN(OP,DESC) LABEL(OP), + #define OPCODE2_RETURN(OP,DESC) LABEL(OP), + #define OPCODE0_TAILRETURN(OP,DESC) LABEL(OP), + #define OPCODE1_TAILRETURN(OP,DESC) LABEL(OP), + #define OPCODE2_TAILRETURN(OP,DESC) LABEL(OP), +  +  init_strap: +  strap = &&normal_strap; +  { +  static void *table[] = { +  NULL_LABEL(F_OFFSET), +  +  NULL_LABEL(F_PREFIX_256), +  NULL_LABEL(F_PREFIX_512), +  NULL_LABEL(F_PREFIX_768), +  NULL_LABEL(F_PREFIX_1024), +  NULL_LABEL(F_PREFIX_CHARX256), +  NULL_LABEL(F_PREFIX_WORDX256), +  NULL_LABEL(F_PREFIX_24BITX256), +  +  NULL_LABEL(F_PREFIX2_256), +  NULL_LABEL(F_PREFIX2_512), +  NULL_LABEL(F_PREFIX2_768), +  NULL_LABEL(F_PREFIX2_1024), +  NULL_LABEL(F_PREFIX2_CHARX256), +  NULL_LABEL(F_PREFIX2_WORDX256), +  NULL_LABEL(F_PREFIX2_24BITX256), +  + #include "interpret_protos.h" +  }; +  +  static struct op_2_f lookup[] = { + #undef LABEL + #define LABEL(OP) { &&PIKE_CONCAT(LABEL_, OP), OP } + #undef NULL_LABEL + #define NULL_LABEL(OP) { NULL, OP } +  +  NULL_LABEL(F_OFFSET), +  +  NULL_LABEL(F_PREFIX_256), +  NULL_LABEL(F_PREFIX_512), +  NULL_LABEL(F_PREFIX_768), +  NULL_LABEL(F_PREFIX_1024), +  NULL_LABEL(F_PREFIX_CHARX256), +  NULL_LABEL(F_PREFIX_WORDX256), +  NULL_LABEL(F_PREFIX_24BITX256), +  +  NULL_LABEL(F_PREFIX2_256), +  NULL_LABEL(F_PREFIX2_512), +  NULL_LABEL(F_PREFIX2_768), +  NULL_LABEL(F_PREFIX2_1024), +  NULL_LABEL(F_PREFIX2_CHARX256), +  NULL_LABEL(F_PREFIX2_WORDX256), +  NULL_LABEL(F_PREFIX2_24BITX256), +  + #include "interpret_protos.h" +  }; +  + #ifdef PIKE_DEBUG +  if (sizeof(table) != (F_MAX_OPCODE-F_OFFSET)*sizeof(void *)) +  Pike_fatal("opcode_to_label out of sync: 0x%08lx != 0x%08lx\n", +  DO_NOT_WARN((long)sizeof(table)), +  DO_NOT_WARN((long)((F_MAX_OPCODE-F_OFFSET)*sizeof(void *)))); + #endif /* PIKE_DEBUG */ +  fcode_to_opcode = table; +  opcode_to_fcode = lookup; +  +  qsort(lookup, F_MAX_OPCODE-F_OFFSET, sizeof(struct op_2_f), +  lookup_sort_fun); +  +  return 0;    } -  + #endif /* HAVE_COMPUTED_GOTO */   }