pike.git / src / docode.c

version» Context lines:

pike.git/src/docode.c:437:    return !!CAR(n)+!!CDR(n);       default:    ret=0;    if(car_is_node(n)) ret += count_cases(CAR(n));    if(cdr_is_node(n)) ret += count_cases(CDR(n));    return ret;    }   }    + static INT32 count_continue_returns(node *n) + { +  INT32 ret; +  if(!n) return 0; +  switch(n->token) +  { +  case F_DO: +  case F_FOR: +  case F_FOREACH: +  case F_LOOP: +  case F_INC_LOOP: +  case F_DEC_LOOP: +  case F_INC_NEQ_LOOP: +  case F_DEC_NEQ_LOOP: +  case F_SWITCH: +  case '?': +  return 0; +  +  case F_CASE: +  return 0; +  case F_CASE_RANGE: +  return 0; +  +  case F_RETURN: +  if (CDR(n) && CDR(n)->u.sval.u.integer) return 1; +  return 0; +  +  default: +  ret=0; +  if(car_is_node(n)) ret += count_continue_returns(CAR(n)); +  if(cdr_is_node(n)) ret += count_continue_returns(CDR(n)); +  return ret; +  } + } +    static int has_automap(node *n)   {    if(!n) return 0;    switch(n->token)    {    case F_AUTO_MAP_MARKER:    case F_AUTO_MAP:    return 1;       default:
pike.git/src/docode.c:2128:    /* Restore root->parent. */    root->parent = parent;    }    return (INT32)tmp1;          /* Switch:    * So far all switches are implemented with a binsearch lookup.    * It stores the case values in the programs area for constants.    * It also has a jump-table in the program itself, for every index in -  * the array of cases, there is 2 indexes in the jumptable, and one extra. +  * the array of cases, there are 2 indexes in the jumptable, and one extra.    * The first entry in the jumptable is used if you call switch with    * a value that is ranked lower than all the indexes in the array of    * cases. (Ranked by the binsearch that is) The second is used if it    * is equal to the first index. The third if it is greater than the    * first, but lesser than the second. The fourth if it is equal to    * the second.... etc. etc.    */       case F_SWITCH:    {
pike.git/src/docode.c:2255:       POP_STATEMENT_LABEL;    BLOCK_END;   #ifdef PIKE_DEBUG    if(Pike_interpreter.recoveries && Pike_sp-Pike_interpreter.evaluator_stack < Pike_interpreter.recoveries->stack_pointer)    Pike_fatal("Stack error after F_SWITCH (underflow)\n");   #endif    return 0;    }    +  case F_GENERATOR: +  { +  int e, states; +  INT32 *jumptable; +  int label; +  +  emit1(F_LOCAL, Pike_compiler->compiler_frame->generator_local); +  tmp1 = emit1(F_SWITCH, 0); +  /* modify_stack_depth(-1); */ +  emit1(F_ALIGN, sizeof(INT32)); +  +  /* NB: Three implicit states: +  * -1: return UNDEFINED; // Termination state. +  * 0: return generator; // Initial state. +  * 1: code // Code start. +  * +  * jumptable: +  * +  * jmp_index case_index case_value label +  * 0 - - Terminate +  * 1 0 0 Initial +  * 2 - 1 Start +  * 3 1 2 Cont #0 +  * ... +  * n+3 (n+3)>>1 n+2 Cont #n +  * n+4 - - Terminate +  * [n+5 (n+5)>>1 n+4 Terminate] +  * +  * Note that an extra case entry is required when there +  * is an even number of states. Thus the 5 in the +  * allocations below. +  */ +  states = count_continue_returns(CAR(n)); +  +  Pike_compiler->compiler_frame->generator_index = 0; +  Pike_compiler->compiler_frame->generator_jumptable = +  xalloc(sizeof(INT32)*(states+5)); +  jumptable = xalloc(sizeof(INT32)*(states+5)); +  +  for (e = 0; e < states+6; e++) { +  jumptable[e] = (INT32)emit1(F_POINTER, 0); +  Pike_compiler->compiler_frame->generator_jumptable[e] = -1; +  } +  emit0(F_NOTREACHED); +  +  /* Termination state. (-1, default) */ +  Pike_compiler->compiler_frame->generator_jumptable[ +  Pike_compiler->compiler_frame->generator_index++] = ins_label(-1); +  emit0(F_UNDEFINED); +  emit0(F_RETURN); +  +  /* Return generator state. (0) */ +  Pike_compiler->compiler_frame->generator_jumptable[ +  Pike_compiler->compiler_frame->generator_index++] = ins_label(-1); +  emit2(F_TRAMPOLINE, +  Pike_compiler->compiler_frame->current_function_number, 0); +  emit1(F_NUMBER, Pike_compiler->compiler_frame->generator_index); +  emit1(F_ASSIGN_LOCAL_AND_POP, +  Pike_compiler->compiler_frame->generator_local); +  emit0(F_RETURN); +  +  /* Entry state. (1) */ +  Pike_compiler->compiler_frame->generator_jumptable[ +  Pike_compiler->compiler_frame->generator_index++] = ins_label(-1); +  DO_CODE_BLOCK(CAR(n)); +  +  /* Update the jump table. */ +  Pike_compiler->compiler_frame->generator_jumptable[ +  Pike_compiler->compiler_frame->generator_index++] = +  Pike_compiler->compiler_frame->generator_jumptable[0]; +  Pike_compiler->compiler_frame->generator_jumptable[ +  Pike_compiler->compiler_frame->generator_index++] = +  Pike_compiler->compiler_frame->generator_jumptable[0]; +  +  for (e = 0; e < Pike_compiler->compiler_frame->generator_index; e++) { +  fprintf(stderr, "e: %d: ptr: 0x%08lx, label: %d\n", +  e, jumptable[e], +  Pike_compiler->compiler_frame->generator_jumptable[e]); +  update_arg(jumptable[e], +  Pike_compiler->compiler_frame->generator_jumptable[e]); +  } +  fprintf(stderr, "Generating table for %d states: \n", states); +  for (e = 0; e < states+5; e += 2) { +  fprintf(stderr, " %d\n", e); +  push_int(e); +  } +  f_aggregate((states + 6)>>1); +  +  fprintf(stderr, "Table: "); +  print_svalue(stderr, Pike_sp-1); +  fprintf(stderr, "\n"); +  +  update_arg((INT32)tmp1, store_constant(Pike_sp-1, 1, 0)); +  pop_stack(); +  +  return 0; +  } +     case F_CASE:    case F_CASE_RANGE:    {    if(!current_switch.jumptable)    {    yyerror("Case outside switch.");    }else{    INT32 label = ins_label(-1);    int i;   
pike.git/src/docode.c:2455:    "Label %S not used.", name.str);    }    POP_STATEMENT_LABEL;    BLOCK_END;    return 0;    }       case F_RETURN: {    struct statement_label *p;    int in_catch = 0; +  int continue_label = -1;    do_docode(CAR(n),0);       /* Insert the appropriate number of F_ESCAPE_CATCH. The rest of    * the cleanup is handled wholesale in low_return et al.    * Alternatively we could handle this too in low_return and    * then allow tail recursion of these kind of returns too. */    for (p = current_label; p; p = p->prev) {    struct cleanup_frame *q;    for (q = p->cleanups; q; q = q->prev) {    if (q->cleanup == (cleanup_func) do_escape_catch) {
pike.git/src/docode.c:2483: Inside #if defined(PIKE_DEBUG)
   q->cleanup == (cleanup_func) do_cleanup_synch_mark) {    /* Use the ordinary pop mark instruction here since we know    * the stack isn't in synch and we don't want debug checks    * for that. */    do_pop_mark (NULL);    }   #endif    }    }    +  if (Pike_compiler->compiler_frame->generator_local != -1) { +  if (CDR(n) && CDR(n)->u.sval.u.integer) { +  /* Continue return. */ +  continue_label = alloc_label(); +  emit1(F_NUMBER, +  Pike_compiler->compiler_frame->generator_index); +  } else { +  emit1(F_NUMBER, -1); +  } +  emit1(F_ASSIGN_LOCAL_AND_POP, +  Pike_compiler->compiler_frame->generator_local); +  } +     emit0(in_catch ? F_VOLATILE_RETURN : F_RETURN); -  +  +  if (continue_label != -1) { +  Pike_compiler->compiler_frame->generator_jumptable[ +  Pike_compiler->compiler_frame->generator_index++] = +  ins_label(continue_label); +  }    return 0;    }       case F_SSCANF:    tmp1=do_docode(CAR(n),DO_NOT_COPY);    tmp2=do_docode(CDR(n),DO_NOT_COPY | DO_LVALUE);    emit1(F_SSCANF, (INT32)(tmp1+tmp2));    return 1;       case F_CATCH: {