pike.git / src / las.c

version» Context lines:

pike.git/src/las.c:1:   /*\   ||| This file a part of Pike, and is copyright by Fredrik Hubinette   ||| Pike is distributed as GPL (General Public License)   ||| See the files COPYING and DISCLAIMER for more information.   \*/   /**/   #include "global.h" - RCSID("$Id: las.c,v 1.107 1999/11/14 19:20:31 grubba Exp $"); + RCSID("$Id: las.c,v 1.108 1999/11/17 02:50:34 grubba Exp $");      #include "language.h"   #include "interpret.h"   #include "las.h"   #include "array.h"   #include "object.h"   #include "stralloc.h"   #include "dynamic_buffer.h"   #include "lex.h"   #include "pike_types.h"
pike.git/src/las.c:30:   #include "builtin_functions.h"   #include "cyclic.h"   #include "block_alloc.h"      #define LASDEBUG      int lasdebug=0;      static node *eval(node *);   static void optimize(node *n); + static node *localopt(node *n);      node *init_node = 0;   int num_parse_error;   int cumulative_parse_error=0;   extern char *get_type_name(int);      #define MAX_GLOBAL 2048    - int car_is_node(node *n) + int car_is_node(const node *n)   {    switch(n->token)    {    case F_EXTERNAL:    case F_IDENTIFIER:    case F_TRAMPOLINE:    case F_CONSTANT:    case F_LOCAL:    return 0;       default:    return !!_CAR(n);    }   }    - int cdr_is_node(node *n) + int cdr_is_node(const node *n)   {    switch(n->token)    {    case F_EXTERNAL:    case F_IDENTIFIER:    case F_TRAMPOLINE:    case F_CONSTANT:    case F_LOCAL:    case F_CAST:    return 0;
pike.git/src/las.c:250: Inside #if defined(SHARED_NODES)
   if (!prior) {    return;    }    prior->next = n->next;    }   }      static node *freeze_node(node *orig)   {    unsigned INT32 hash = hash_node(orig); -  node *n = node_hash.table[hash % node_hash.size]; +  node *n;       /* free_node() wants a correct hash */    orig->hash = hash;       if (orig->node_info & OPT_NOT_SHARED) {    /* No need to have this node in the hash-table. */    /* add_node(orig); */    return check_node_hash(dmalloc_touch(node *, orig));    }    -  +  /* Mark this node as a possible duplicate */ +  orig->node_info |= OPT_DEFROSTED; +  /* Make sure we don't find ourselves */ +  sub_node(orig); +  +  n = node_hash.table[hash % node_hash.size]; +     while (n) {    if ((n->hash == hash) &&    !MEMCMP(&(n->token), &(orig->token),    sizeof(node) - OFFSETOF(node_s, token))) { - #ifdef PIKE_DEBUG -  if (n == orig) { -  fatal("Node to be frozen was already cold!\n"); -  } - #endif /* PIKE_DEBUG */ +     free_node(dmalloc_touch(node *, orig));    n->refs++;    return check_node_hash(dmalloc_touch(node *, n));    }    n = n->next;    } -  +  orig->node_info &= ~OPT_DEFROSTED;    add_node(dmalloc_touch(node *, orig));    return check_node_hash(orig);   }      #else /* !SHARED_NODES */      #define freeze_node(X) (X)      #endif /* SHARED_NODES */   
pike.git/src/las.c:2153:      static void zapp_try_optimize(node *n)   {    if(!n) return;    n->node_info &=~ OPT_TRY_OPTIMIZE;    n->tree_info &=~ OPT_TRY_OPTIMIZE;    if(car_is_node(n)) zapp_try_optimize(CAR(n));    if(cdr_is_node(n)) zapp_try_optimize(CDR(n));   }    + #if defined(SHARED_NODES) && !defined(IN_TPIKE) + static void find_usage(const node *n, unsigned char *usage, +  unsigned char *switch_u, +  const unsigned char *cont_u, +  const unsigned char *break_u) + { +  if (!n) +  return; +  +  switch(n->token) { +  case F_ASSIGN: +  if ((CDR(n)->token == F_LOCAL) && (!CDR(n)->u.integer.b)) { +  usage[CDR(n)->u.integer.a] = 0; +  } +  find_usage(CAR(n), usage, switch_u, cont_u, break_u); +  return; +  +  case F_CONTINUE: +  MEMCPY(usage, cont_u, MAX_LOCAL); +  return; +  +  case F_BREAK: +  MEMCPY(usage, break_u, MAX_LOCAL); +  return; +  +  case F_DEFAULT: +  case F_CASE: +  { +  int i; +  +  find_usage(CDR(n), usage, switch_u, cont_u, break_u); +  find_usage(CAR(n), usage, switch_u, cont_u, break_u); +  for(i = 0; i < MAX_LOCAL; i++) { +  switch_u[i] |= usage[i]; +  } +  return; +  } +  +  case F_SWITCH: +  { +  unsigned char break_usage[MAX_LOCAL]; +  unsigned char switch_usage[MAX_LOCAL]; +  int i; +  +  MEMSET(switch_usage, 0, MAX_LOCAL); +  MEMCPY(break_usage, usage, MAX_LOCAL); +  +  find_usage(CDR(n), usage, switch_usage, cont_u, break_usage); +  +  for(i = 0; i < MAX_LOCAL; i++) { +  usage[i] |= switch_usage[i]; +  } +  +  find_usage(CAR(n), usage, switch_u, cont_u, break_u); +  return; +  } +  +  case F_RETURN: +  MEMSET(usage, 0, MAX_LOCAL); +  /* FIXME: The function arguments should be marked "used", since +  * they are seen in backtraces. +  */ +  return; +  +  case F_LOR: +  case F_LAND: +  { +  unsigned char trail_usage[MAX_LOCAL]; +  int i; +  +  MEMCPY(trail_usage, usage, MAX_LOCAL); +  +  find_usage(CDR(n), usage, switch_u, cont_u, break_u); +  +  for(i=0; i < MAX_LOCAL; i++) { +  usage[i] |= trail_usage[i]; +  } +  +  find_usage(CAR(n), usage, switch_u, cont_u, break_u); +  return; +  } +  +  case '?': +  { +  unsigned char cadr_usage[MAX_LOCAL]; +  unsigned char cddr_usage[MAX_LOCAL]; +  int i; +  +  MEMCPY(cadr_usage, usage, MAX_LOCAL); +  MEMCPY(cddr_usage, usage, MAX_LOCAL); +  +  find_usage(CADR(n), cadr_usage, switch_u, cont_u, break_u); +  find_usage(CDDR(n), cadr_usage, switch_u, cont_u, break_u); +  +  for (i=0; i < MAX_LOCAL; i++) { +  usage[i] = cadr_usage[i] | cddr_usage[i]; +  } +  find_usage(CAR(n), usage, switch_u, cont_u, break_u); +  return; +  } +  +  case F_DO: +  { +  unsigned char break_usage[MAX_LOCAL]; +  unsigned char continue_usage[MAX_LOCAL]; +  +  MEMCPY(break_usage, usage, MAX_LOCAL); +  +  find_usage(CDR(n), usage, switch_u, cont_u, break_usage); +  +  MEMCPY(continue_usage, usage, MAX_LOCAL); +  +  find_usage(CAR(n), usage, switch_u, break_usage, continue_usage); +  return; +  } +  +  case F_FOR: +  { +  unsigned char break_usage[MAX_LOCAL]; +  unsigned char continue_usage[MAX_LOCAL]; +  node *car1, cadr, cddr; +  +  MEMCPY(break_usage, usage, MAX_LOCAL); +  +  /* for(;a;b) c; is handled like: +  * +  * if (a) { do { c; b; } while(a); } +  */ +  find_usage(CAR(n), usage, switch_u, cont_u, break_u); +  find_usage(CDDR(n), usage, switch_u, cont_u, break_usage); +  +  MEMCPY(continue_usage, usage, MAX_LOCAL); +  +  find_usage(CADR(n), usage, switch_u, continue_usage, break_usage); +  +  find_usage(CAR(n), usage, switch_u, cont_u, break_u); +  return; +  } +  +  case F_FOREACH: +  { +  unsigned char break_usage[MAX_LOCAL]; +  unsigned char continue_usage[MAX_LOCAL]; +  +  MEMCPY(break_usage, usage, MAX_LOCAL); +  +  /* Find the usage from the body */ +  find_usage(CDR(n), usage, switch_u, cont_u, break_usage); +  +  MEMCPY(continue_usage, usage, MAX_LOCAL); +  +  find_usage(CDR(n), usage, switch_u, continue_usage, break_usage); +  find_usage(CAAR(n), usage, switch_u, cont_u, break_u); +  return; +  } +  +  case F_LOCAL: +  /* Use of local variable. */ +  if (!n->u.integer.b) { +  /* Recently used, and used at all */ +  usage[n->u.integer.a] = 3; +  } +  return; +  +  default: +  if (cdr_is_node(n)) { +  find_usage(CDR(n), usage, switch_u, cont_u, break_u); +  } +  if (car_is_node(n)) { +  find_usage(CAR(n), usage, switch_u, cont_u, break_u); +  } +  return; +  } + } +  + /* Note: Always builds a new tree. */ + static node *low_localopt(node *n, +  unsigned char *usage, +  unsigned char *switch_u, +  const unsigned char *cont_u, +  const unsigned char *break_u) + { +  node *car, *cdr; +  +  if (!n) +  return NULL; +  +  switch(n->token) { +  case F_ASSIGN: +  if ((CDR(n)->token == F_LOCAL) && (!CDR(n)->u.integer.b)) { +  /* Assignment of local variable */ +  if (!(usage[CDR(n)->u.integer.a] & 1)) { +  /* Value isn't used. */ +  return low_localopt(CAR(n), usage, switch_u, cont_u, break_u); +  } +  usage[CDR(n)->u.integer.a] = 0; +  } +  ADD_NODE_REF(CDR(n)); +  return mknode(F_ASSIGN, low_localopt(CAR(n), usage, switch_u, cont_u, +  break_u), CDR(n)); +  +  case F_CAST: +  return mkcastnode(n->type, low_localopt(CAR(n), usage, switch_u, cont_u, +  break_u)); +  +  case F_CONTINUE: +  MEMCPY(usage, cont_u, MAX_LOCAL); +  ADD_NODE_REF(n); +  return n; +  +  case F_BREAK: +  MEMCPY(usage, break_u, MAX_LOCAL); +  ADD_NODE_REF(n); +  return n; +  +  case F_DEFAULT: +  case F_CASE: +  { +  int i; +  +  cdr = low_localopt(CDR(n), usage, switch_u, cont_u, break_u); +  car = low_localopt(CAR(n), usage, switch_u, cont_u, break_u); +  for(i = 0; i < MAX_LOCAL; i++) { +  switch_u[i] |= usage[i]; +  } +  return mknode(n->token, car, cdr); +  } +  +  case F_SWITCH: +  { +  unsigned char break_usage[MAX_LOCAL]; +  unsigned char switch_usage[MAX_LOCAL]; +  int i; +  +  MEMSET(switch_usage, 0, MAX_LOCAL); +  MEMCPY(break_usage, usage, MAX_LOCAL); +  +  cdr = low_localopt(CDR(n), usage, switch_usage, cont_u, break_usage); +  +  for(i = 0; i < MAX_LOCAL; i++) { +  usage[i] |= switch_usage[i]; +  } +  +  car = low_localopt(CAR(n), usage, switch_u, cont_u, break_u); +  return mknode(F_SWITCH, car, cdr); +  } +  +  case F_RETURN: +  MEMSET(usage, 0, MAX_LOCAL); +  /* FIXME: The function arguments should be marked "used", since +  * they are seen in backtraces. +  */ +  return mknode(F_RETURN, low_localopt(CAR(n), usage, switch_u, cont_u, +  break_u), 0); +  +  case F_LOR: +  case F_LAND: +  { +  unsigned char trail_usage[MAX_LOCAL]; +  int i; +  +  MEMCPY(trail_usage, usage, MAX_LOCAL); +  +  cdr = low_localopt(CDR(n), usage, switch_u, cont_u, break_u); +  +  for(i=0; i < MAX_LOCAL; i++) { +  usage[i] |= trail_usage[i]; +  } +  +  car = low_localopt(CAR(n), usage, switch_u, cont_u, break_u); +  +  return mknode(n->token, car, cdr); +  } +  +  case '?': +  { +  unsigned char cadr_usage[MAX_LOCAL]; +  unsigned char cddr_usage[MAX_LOCAL]; +  int i; +  +  MEMCPY(cadr_usage, usage, MAX_LOCAL); +  MEMCPY(cddr_usage, usage, MAX_LOCAL); +  +  car = low_localopt(CADR(n), cadr_usage, switch_u, cont_u, break_u); +  cdr = low_localopt(CDDR(n), cadr_usage, switch_u, cont_u, break_u); +  +  for (i=0; i < MAX_LOCAL; i++) { +  usage[i] = cadr_usage[i] | cddr_usage[i]; +  } +  cdr = mknode(':', car, cdr); +  car = low_localopt(CAR(n), usage, switch_u, cont_u, break_u); +  return mknode('?', car, cdr); +  } +  +  case F_DO: +  { +  unsigned char break_usage[MAX_LOCAL]; +  unsigned char continue_usage[MAX_LOCAL]; +  +  MEMCPY(break_usage, usage, MAX_LOCAL); +  +  /* Find the usage from the body */ +  find_usage(n, usage, switch_u, cont_u, break_usage); +  cdr = low_localopt(CDR(n), usage, switch_u, cont_u, break_usage); +  +  MEMCPY(continue_usage, usage, MAX_LOCAL); +  +  car = low_localopt(CAR(n), usage, switch_u, continue_usage, break_usage); +  +  return mknode(F_DO, car, cdr); +  } +  +  case F_FOR: +  { +  unsigned char break_usage[MAX_LOCAL]; +  unsigned char continue_usage[MAX_LOCAL]; +  node *car1, *cadr, *cddr; +  +  MEMCPY(break_usage, usage, MAX_LOCAL); +  +  /* Find the usage from the body. */ +  find_usage(n, usage, switch_u, cont_u, break_usage); +  +  /* for(;a;b) c; is handled like: +  * +  * if (a) { do { c; b; } while(a); } +  */ +  car = low_localopt(CAR(n), usage, switch_u, cont_u, break_u); +  cddr = low_localopt(CDDR(n), usage, switch_u, cont_u, break_usage); +  +  MEMCPY(continue_usage, usage, MAX_LOCAL); +  +  cadr = low_localopt(CADR(n), usage, switch_u, continue_usage, +  break_usage); +  cdr = mknode(':', cadr, cddr); +  +  /* We need to update the usage set */ +  find_usage(car, usage, switch_u, cont_u, break_u); +  +  return mknode(F_FOR, car, cdr); +  } +  +  case F_FOREACH: +  { +  unsigned char break_usage[MAX_LOCAL]; +  unsigned char continue_usage[MAX_LOCAL]; +  +  MEMCPY(break_usage, usage, MAX_LOCAL); +  +  /* Find the usage from the body */ +  find_usage(CDR(n), usage, switch_u, cont_u, break_usage); +  +  MEMCPY(continue_usage, usage, MAX_LOCAL); +  cdr = low_localopt(CDR(n), usage, switch_u, continue_usage, break_usage); +  car = low_localopt(CAAR(n), usage, switch_u, cont_u, break_u); +  ADD_NODE_REF(CDAR(n)); +  return mknode(F_FOREACH, mknode(F_VAL_LVAL, car, CDAR(n)), cdr); +  } +  +  case F_LOCAL: +  /* Use of local variable. */ +  if (!n->u.integer.b) { +  /* Recently used, and used at all */ +  usage[n->u.integer.a] = 3; +  } +  ADD_NODE_REF(n); +  return n; +  +  default: +  if (cdr_is_node(n)) { +  cdr = low_localopt(CDR(n), usage, switch_u, cont_u, break_u); +  return mknode(n->token, low_localopt(CAR(n), usage, switch_u, cont_u, +  break_u), +  cdr); +  } +  if (car_is_node(n)) { +  ADD_NODE_REF(CDR(n)); +  return mknode(n->token, low_localopt(CAR(n), usage, switch_u, cont_u, +  break_u), +  CDR(n)); +  } +  ADD_NODE_REF(n); +  return n; +  } + } +  + static node *localopt(node *n) + { +  unsigned char usage[MAX_LOCAL]; +  unsigned char b_usage[MAX_LOCAL]; +  unsigned char c_usage[MAX_LOCAL]; +  unsigned char s_usage[MAX_LOCAL]; +  node *n2; +  +  MEMSET(usage, 0, MAX_LOCAL); +  MEMSET(b_usage, 0, MAX_LOCAL); +  MEMSET(c_usage, 0, MAX_LOCAL); +  MEMSET(s_usage, 0, MAX_LOCAL); +  +  fprintf(stderr, "Localopt: "); +  print_tree(n); +  +  n2 = low_localopt(n, usage, s_usage, c_usage, b_usage); +  free_node(n); +  +  fprintf(stderr, "Done: "); +  print_tree(n2); +  +  return n2; + } + #endif /* SHARED_NODES && !IN_TPIKE */ +    static void optimize(node *n)   {    node *tmp1, *tmp2, *tmp3;    INT32 save_line = lex.current_line;    do    {    if(car_is_node(n) &&    ((CAR(n)->node_info & (OPT_OPTIMIZED|OPT_DEFROSTED)) != OPT_OPTIMIZED))    {    CAR(n)->parent = n;
pike.git/src/las.c:2180:    n = CDR(n);    continue;    }      #if defined(SHARED_NODES)    if ((n->node_info & OPT_DEFROSTED) && (n->parent)) {   #ifndef IN_TPIKE    /* Add ref since both freeze_node() and use_tmp1 will free it. */    ADD_NODE_REF(n);    /* We don't want freeze_node() to find this node in the hash-table. */ -  sub_node(n); +     tmp1 = freeze_node(n);    if (tmp1 != n) {    /* n was a duplicate node. Use the original. */    goto use_tmp1;    }    /* Remove the extra ref from n */    free_node(n); - #endif /* !IN_TPIKE */ -  /* The node is now frozen again. */ + #else /* IN_TPIKE */    n->node_info &= ~OPT_DEFROSTED; -  + #endif /* !IN_TPIKE */    if (n->node_info & OPT_OPTIMIZED) {    /* No need to check this node any more. */    n = n->parent;    continue;    }    }   #endif /* SHARED_NODES && !IN_TPIKE */       lex.current_line = n->line_number;   
pike.git/src/las.c:2618:    {    tmp.offset=-1;   #ifdef PIKE_DEBUG    if(a_flag > 4)    {    fprintf(stderr,"Making prototype (pass 1) for: ");    print_tree(n);    }   #endif    }else{ -  n=mknode(F_ARG_LIST,check_node_hash(n),0); + #if defined(SHARED_NODES) && !defined(IN_TPIKE) +  /* Try the local variable usage analyser. */ +  n = localopt(check_node_hash(n)); +  /* Try optimizing some more. */ +  optimize(n); + #endif /* SHARED_NODES && !IN_TPIKE */ +  n = mknode(F_ARG_LIST,check_node_hash(n),0);       if((foo=is_stupid_func(check_node_hash(n), args, vargs, type)))    {    if(foo->type == T_FUNCTION && foo->subtype==FUNCTION_BUILTIN)    {    tmp.c_fun=foo->u.efun->function;    ret=define_function(name,    type,    modifiers,    IDENTIFIER_C_FUNCTION | vargs,