pike.git / src / encode.c

version» Context lines:

pike.git/src/encode.c: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. - || $Id: encode.c,v 1.200 2003/11/17 14:39:47 grubba Exp $ + || $Id: encode.c,v 1.201 2003/11/25 15:59:41 grubba Exp $   */      #include "global.h"   #include "stralloc.h"   #include "pike_macros.h"   #include "object.h"   #include "constants.h"   #include "interpret.h"   #include "svalue.h"   #include "mapping.h"
pike.git/src/encode.c:23:   #include "builtin_functions.h"   #include "module_support.h"   #include "fsort.h"   #include "threads.h"   #include "stuff.h"   #include "version.h"   #include "bignum.h"   #include "pikecode.h"   #include "pike_types.h"   #include "opcodes.h" + #include "peep.h"    - RCSID("$Id: encode.c,v 1.200 2003/11/17 14:39:47 grubba Exp $"); + RCSID("$Id: encode.c,v 1.201 2003/11/25 15:59:41 grubba Exp $");      /* #define ENCODE_DEBUG */      /* Use the old encoding method for programs. */   /* #define OLD_PIKE_ENCODE_PROGRAM */      #ifdef ENCODE_DEBUG   /* Pass a nonzero integer as the third arg to encode_value,    * encode_value_canonic and decode_value to activate this debug. */   #define EDB(N,X) do { debug_malloc_touch(data); if (data->debug>=N) {X;} } while (0)
pike.git/src/encode.c:100:   #define TAG_DELAYED 14 /* Note: Coincides with T_ZERO. */   #define TAG_AGAIN 15   #define TAG_MASK 15   #define TAG_NEG 16   #define TAG_SMALL 32   #define SIZE_SHIFT 6   #define MAX_SMALL (1<<(8-SIZE_SHIFT))   #define COUNTER_START (-MAX_SMALL)      /* Entries used to encode the identifier_references table. */ + #define ID_ENTRY_EFUN_CONSTANT -3   #define ID_ENTRY_RAW -2   #define ID_ENTRY_EOT -1   #define ID_ENTRY_VARIABLE 0   #define ID_ENTRY_FUNCTION 1   #define ID_ENTRY_CONSTANT 2   #define ID_ENTRY_INHERIT 3      struct encode_data   {    int canonic;
pike.git/src/encode.c:1185:    encode_value2(Pike_sp-1, data, 0);    pop_stack();       /* num_* */   #define FOO(NUMTYPE,TYPE,ARGTYPE,NAME) \    code_number( p->PIKE_CONCAT(num_,NAME), data);   #include "program_areas.h"       /* Byte-code method    */ + #ifdef PIKE_PORTABLE_BYTECODE +  code_number(PIKE_BYTECODE_PORTABLE, data); + #else /* !PIKE_PORTABLE_BYTECODE */    code_number(PIKE_BYTECODE_METHOD, data); -  +    #ifdef PIKE_USE_MACHINE_CODE    /* Add the checksum of the instrs array. */    code_number(instrs_checksum, data);   #endif /* PIKE_USE_MACHINE_CODE */       /* program */   #ifdef ENCODE_PROGRAM   #ifdef PIKE_DEBUG    {    ptrdiff_t bufpos = data->buf.s.len;
pike.git/src/encode.c:1222:   #endif /* ENCODE_PROGRAM */       /* relocations */    for(d=0; d<(int)p->num_relocations; d++) {    code_number(p->relocations[d], data);    }       /* linenumbers */    adddata2(p->linenumbers, p->num_linenumbers);    + #endif /* PIKE_PORTABLE_BYTECODE */ +     {    struct svalue str_sval;    str_sval.type = T_STRING;    str_sval.subtype = 0;    /* strings */    for(d=0;d<p->num_strings;d++) {    str_sval.u.string = p->strings[d];    encode_value2(&str_sval, data, 0);    }    }       EDB(5, dump_program_tables(p, data->depth));    -  + #ifdef PIKE_PORTABLE_BYTECODE +  /* Encode the efun constants since they are needed by the optimizer. */ +  { +  struct svalue str_sval; +  str_sval.type = T_STRING; +  str_sval.subtype = 0; +  +  /* constants */ +  for(d=0;d<p->num_constants;d++) +  { +  if ((p->constants[d].sval.type != T_FUNCTION) || +  (p->constants[d].sval.subtype != FUNCTION_BUILTIN)) { +  continue; +  } +  code_number(ID_ENTRY_EFUN_CONSTANT, data); +  code_number(d, data); +  /* value */ +  encode_value2(&p->constants[d].sval, data, 0); +  +  /* name */ +  if (p->constants[d].name) { +  str_sval.u.string = p->constants[d].name; +  encode_value2(&str_sval, data, 0); +  } else { +  push_int(0); +  encode_value2(Pike_sp-1, data, 0); +  dmalloc_touch_svalue(Pike_sp-1); +  Pike_sp--; +  } +  } +  } + #endif /* PIKE_PORTABLE_BYTECODE */    /* Dump the identifiers in a portable manner... */    {    int inherit_num = 1;    struct svalue str_sval;    char *id_dumped = (char *) alloca(p->num_identifiers);    MEMSET(id_dumped,0,p->num_identifiers);    str_sval.type = T_STRING;    str_sval.subtype = 0;       EDB(2,
pike.git/src/encode.c:1376:       /* type */    ref_push_type_value(id->type);    encode_value2(Pike_sp-1, data, 0);    pop_stack();       /* func_flags (aka identifier_flags) */    code_number(id->identifier_flags, data);       /* func */ + #ifdef PIKE_PORTABLE_BYTECODE +  if (id->func.offset >= 0) { +  /* Code the number of the string containing +  * the raw bytecode. +  */ +  code_number(((INT32 *)(p->program+id->func.offset))[-1], +  data); +  } else { +  /* Prototype */ +  code_number(-1, data); +  } + #else /* !PIKE_PORTABLE_BYTECODE */    code_number(id->func.offset, data); -  + #endif /* PIKE_PORTABLE_BYTECODE */       /* opt_flags */    code_number(id->opt_flags, data);    break;       case IDENTIFIER_C_FUNCTION:    /* Not supported. */    Pike_error("Cannot encode functions implemented in C "    "(identifier='%s').\n",    p->identifiers[d].name->str);
pike.git/src/encode.c:2170:    f_backtrace (0);    f_aggregate (2);       free_svalue(& throw_value);    dmalloc_touch_svalue(Pike_sp-1);    throw_value = *--Pike_sp;    throw_severity = THROW_ERROR;    pike_throw();   }    + /* Decode bytecode string @[string_no]. +  * Returns resulting offset in p->program. +  */ + static INT32 decode_portable_bytecode(INT32 string_no) + { +  struct program *p = Pike_compiler->new_program; +  struct pike_string *bytecode; +  struct pike_string *current_file=NULL; +  INT32 current_line=0; +  int e; +  ONERROR err; +  +  if ((string_no < 0) || (string_no >= p->num_strings)) { +  Pike_error("Bad bytecode string number: %d (expected 0 - %d).\n", +  string_no, p->num_strings-1); +  } +  +  bytecode = p->strings[string_no]; +  +  if (bytecode->len % 3) { +  Pike_error("Bad bytecode string length: %d (expected multiple of 3).\n", +  bytecode->len); +  } +  +  init_bytecode(); +  +  SET_ONERROR(err, exit_bytecode, NULL); +  +  switch(bytecode->size_shift) { + #define EMIT_BYTECODE(STR) do { \ +  for (e = 0; e < bytecode->len; e += 3) { \ +  if (STR(bytecode)[e] == F_FILENAME) { \ +  INT32 strno = STR(bytecode)[e+1]; \ +  if ((strno < 0) || (strno >= p->num_strings)) { \ +  Pike_error("Bad filename directive number:" \ +  " %d (expected 0 - %d).\n", \ +  strno, p->num_strings); \ +  } \ +  current_file = p->strings[strno]; \ +  } else if (STR(bytecode)[e] == F_LINE) { \ +  current_line = STR(bytecode)[e+1]; \ +  } else { \ +  insert_opcode2(STR(bytecode)[e], \ +  STR(bytecode)[e+1], \ +  STR(bytecode)[e+2], \ +  current_line, \ +  current_file); \ +  } \ +  } \ +  } while(0) +  case 2: +  EMIT_BYTECODE(STR2); +  break; +  case 1: +  EMIT_BYTECODE(STR1); +  break; +  case 0: +  EMIT_BYTECODE(STR0); +  break; + #undef EMIT_BYTECODE +  default: +  Pike_fatal("Bad size_shift: %d\n", bytecode->size_shift); +  } +  UNSET_ONERROR(err); +  return assemble(1); + } +    static void decode_value2(struct decode_data *data)      #ifdef PIKE_DEBUG   #undef decode_value2   #define decode_value2(X) do { struct svalue *_=Pike_sp; decode_value2_(X); if(Pike_sp!=_+1) Pike_fatal("decode_value2 failed!\n"); } while(0)   #endif         {    INT32 what, e, num, numh;
pike.git/src/encode.c:3354:    dmalloc_touch_svalue(Pike_sp-1);    Pike_sp--;       /* Decode lengths. */   #define FOO(NUMTYPE,TYPE,ARGTYPE,NAME) \    decode_number(PIKE_CONCAT(local_num_, NAME), data);   #include "program_areas.h"       /* Byte-code method */    decode_number(bytecode_method, data); -  if (bytecode_method != PIKE_BYTECODE_METHOD) { +  if (bytecode_method == PIKE_BYTECODE_PORTABLE) { +  } else if (bytecode_method != PIKE_BYTECODE_METHOD) {    Pike_error("Unsupported byte-code method: %d\n", bytecode_method); -  } +  } else {      #ifdef PIKE_USE_MACHINE_CODE    {    size_t csum;    /* Check the checksum of the instrs array. */    decode_number(csum, data);    if (csum != instrs_checksum) {    Pike_error("Bad instruction checksum: %d (expected %d)\n",    csum, instrs_checksum);    }
pike.git/src/encode.c:3413:    }       /* Now with the linenumber info in place it gets useful to    * include the program in error messages. */       EDB(2,    fprintf(stderr, "%*sThe program is: ", data->depth, "");    push_program (p);    print_svalue (stderr, --Pike_sp);    fputc('\n', stderr)); +  }       /* identifier_index & variable_index are created by    * fixate_program() and optimize_program().    */       /* Decode strings */    for (e=0; e<local_num_strings; e++) {    decode_value2(data);    if (Pike_sp[-1].type != T_STRING) {    ref_push_program (p);    decode_error(Pike_sp - 1, Pike_sp - 2,    "Nonstrings in string table: ");    }    add_to_strings(Pike_sp[-1].u.string);    dmalloc_touch_svalue(Pike_sp-1);    Pike_sp--;    }    -  /* Place holder constants. +  /* First pass constants.    *    * These will be replaced later on.    */    {    struct program_constant constant;    constant.name = NULL;    constant.sval.type = T_INT;    constant.sval.subtype = NUMBER_UNDEFINED;    constant.sval.u.integer = 0;   
pike.git/src/encode.c:3455:    }       /* Decode identifier_references, inherits and identifiers. */    decode_number(entry_type, data);    EDB(4,    fprintf(stderr, "%*sDecoding identifier references.\n",    data->depth, ""));   #ifdef ENCODE_DEBUG    data->depth+=2;   #endif +  while (entry_type == ID_ENTRY_EFUN_CONSTANT) { +  struct program_constant *constant; +  decode_number(e, data); +  if ((e < 0) || (e >= local_num_constants)) { +  ref_push_program (p); +  decode_error(Pike_sp - 1, NULL, +  "Bad efun number: %d (expected 0 - %d).\n", +  e, local_num_constants-1); +  } +  constant = p->constants+e; +  /* value */ +  decode_value2(data); +  if ((Pike_sp[-2].type != T_FUNCTION) || +  (Pike_sp[-2].subtype != FUNCTION_BUILTIN)) { +  ref_push_program (p); +  decode_error(Pike_sp - 1, Pike_sp - 2, +  "Expected efun constant: "); +  } +  /* name */ +  decode_value2(data); +  if (Pike_sp[-1].type == T_STRING) { +  constant->name = Pike_sp[-1].u.string; +  } else if ((Pike_sp[-1].type == T_INT) && +  !Pike_sp[-1].u.integer) { +  constant->name = NULL; +  } else { +  ref_push_program (p); +  decode_error(Pike_sp - 1, Pike_sp - 2, +  "Name of constant is not a string: "); +  } +  constant->sval = Pike_sp[-2]; +  dmalloc_touch_svalue(Pike_sp-1); +  dmalloc_touch_svalue(Pike_sp-2); +  Pike_sp -= 2; +  decode_number(entry_type, data); +  }    while (entry_type != ID_ENTRY_EOT) {    decode_number(id_flags, data);    switch(entry_type) {    case ID_ENTRY_RAW:    {    int no;    int ref_no;    struct reference ref;       /* id_flags */
pike.git/src/encode.c:3571:    ref_push_program (p);    decode_error(Pike_sp - 1, Pike_sp - 2,    "Bad function type (not a type): ");    }       /* func_flags (aka identifier_flags) */    decode_number(func_flags, data);       /* func */    decode_number(func.offset, data); +  if (bytecode_method == PIKE_BYTECODE_PORTABLE && +  func.offset != -1) { +  func.offset = decode_portable_bytecode(func.offset); +  }       /* opt_flags */    decode_number(opt_flags, data);       /* FIXME:    * Verify validity of func_flags, func.offset & opt_flags    */       /* Expected identifier offset */    decode_number(no, data);
pike.git/src/encode.c:3837:    push_program(p);       /* Restore lex.pragmas. */    CALL_AND_UNSET_ONERROR(err2);       EDB(5, dump_program_tables(p, data->depth));   #ifdef PIKE_DEBUG    check_program (p);   #endif    +  if (bytecode_method == PIKE_BYTECODE_PORTABLE) { +  /* We've regenerated p->program, so this may be off. */ +  local_num_program = p->num_program; +  } +     /* Verify... */   #define FOO(NUMTYPE,TYPE,ARGTYPE,NAME) \    if (PIKE_CONCAT(local_num_, NAME) != p->PIKE_CONCAT(num_,NAME)) { \    ref_push_program (p); \    decode_error(Pike_sp - 1, NULL, \    "Value mismatch for num_" TOSTR(NAME) ": %d != %d\n", \    PIKE_CONCAT(local_num_, NAME), \    p->PIKE_CONCAT(num_, NAME)); \    }   #include "program_areas.h"       /* Decode the actual constants    *    * This must be done after the program has been ended.    */    for (e=0; e<local_num_constants; e++) {    struct program_constant *constant = p->constants+e; -  +  if ((constant->sval.type != T_INT) || +  (constant->sval.subtype != NUMBER_UNDEFINED)) { +  /* Already initialized. */ +  continue; +  }    /* value */    decode_value2(data);    /* name */    decode_value2(data);    if (Pike_sp[-1].type == T_STRING) {    constant->name = Pike_sp[-1].u.string;    } else if ((Pike_sp[-1].type == T_INT) &&    !Pike_sp[-1].u.integer) {    constant->name = NULL;    } else {