e576bb2002-10-11Martin Nilsson /* || 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. */
aedfb12002-10-09Martin Nilsson 
2a50961995-08-23Fredrik Hübinette (Hubbe) #include "global.h"
5267b71995-08-09Fredrik Hübinette (Hubbe) #include "object.h" #include "dynamic_buffer.h" #include "interpret.h" #include "program.h" #include "stralloc.h" #include "svalue.h"
bb55f81997-03-16Fredrik Hübinette (Hubbe) #include "pike_macros.h"
9aa6fa1997-05-19Fredrik Hübinette (Hubbe) #include "pike_memory.h"
b2d3e42000-12-01Fredrik Hübinette (Hubbe) #include "pike_error.h"
5267b71995-08-09Fredrik Hübinette (Hubbe) #include "main.h"
4a66491995-11-13Per Hedbor #include "array.h"
624d091996-02-24Fredrik Hübinette (Hubbe) #include "gc.h"
1407c91996-06-09Fredrik Hübinette (Hubbe) #include "backend.h"
a29e021996-10-15Fredrik Hübinette (Hubbe) #include "callback.h"
b1f4eb1998-01-13Fredrik Hübinette (Hubbe) #include "cpp.h" #include "builtin_functions.h"
ba35bf1998-04-14Fredrik Hübinette (Hubbe) #include "cyclic.h"
37775c2004-04-06Martin Nilsson #include "pike_security.h"
a5787d1999-03-03Fredrik Hübinette (Hubbe) #include "module_support.h"
9a49cb1999-06-19Fredrik Hübinette (Hubbe) #include "fdlib.h"
12666e1999-08-29Fredrik Hübinette (Hubbe) #include "mapping.h"
5e83442008-05-11Martin Stjernholm #include "multiset.h"
4647061999-09-14Fredrik Hübinette (Hubbe) #include "constants.h"
c2f1a01999-11-16Henrik Grubbström (Grubba) #include "encode.h"
a0180b2003-11-14Martin Stjernholm #include "pike_types.h"
9a5d082004-03-16Martin Stjernholm #include "operators.h"
4647061999-09-14Fredrik Hübinette (Hubbe)  #include "block_alloc.h"
5267b71995-08-09Fredrik Hübinette (Hubbe) 
61f3851999-03-11Henrik Grubbström (Grubba) #ifdef HAVE_SYS_TYPES_H #include <sys/types.h> #endif /* HAVE_SYS_TYPES_H */
54166e1998-05-17Henrik Grubbström (Grubba) #ifdef HAVE_SYS_FILE_H #include <sys/file.h> #endif /* HAVE_SYS_FILE_H */
61f3851999-03-11Henrik Grubbström (Grubba) #include <sys/stat.h>
e444911998-04-05Fredrik Hübinette (Hubbe) #include "dmalloc.h"
6ad2372002-05-11Martin Nilsson #define sp Pike_sp
54166e1998-05-17Henrik Grubbström (Grubba) 
d9d6f02001-06-30Martin Stjernholm /* #define GC_VERBOSE */
e8e2532009-08-25Henrik Grubbström (Grubba) /* #define DEBUG */
d9d6f02001-06-30Martin Stjernholm 
54166e1998-05-17Henrik Grubbström (Grubba) #ifndef SEEK_SET #ifdef L_SET #define SEEK_SET L_SET #else /* !L_SET */ #define SEEK_SET 0 #endif /* L_SET */ #endif /* SEEK_SET */ #ifndef SEEK_CUR #ifdef L_INCR #define SEEK_SET L_INCR #else /* !L_INCR */ #define SEEK_CUR 1 #endif /* L_INCR */ #endif /* SEEK_CUR */ #ifndef SEEK_END #ifdef L_XTND #define SEEK_END L_XTND #else /* !L_XTND */ #define SEEK_END 2 #endif /* L_XTND */ #endif /* SEEK_END */
5267b71995-08-09Fredrik Hübinette (Hubbe) struct object *master_object = 0;
6023ae1997-01-18Fredrik Hübinette (Hubbe) struct program *master_program =0;
7a12332003-07-16Martin Stjernholm static int master_is_cleaned_up = 0;
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT struct object *first_object;
5267b71995-08-09Fredrik Hübinette (Hubbe) 
e2d9e62000-06-10Martin Stjernholm struct object *gc_internal_object = 0; static struct object *gc_mark_object_pos = 0;
648a1a2000-06-22Fredrik Hübinette (Hubbe) #undef COUNT_OTHER #define COUNT_OTHER() do{ \ struct object *o; \ for(o=first_object;o;o=o->next) \ if(o->prog) \ size+=o->prog->storage_needed; \ \ for(o=objects_to_destruct;o;o=o->next) \ if(o->prog) \ size+=o->prog->storage_needed; \ }while(0)
3aab372002-11-24Martin Stjernholm BLOCK_ALLOC_FILL_PAGES(object, 2)
648a1a2000-06-22Fredrik Hübinette (Hubbe) 
7a12332003-07-16Martin Stjernholm #undef COUNT_OTHER #define COUNT_OTHER()
fa8c692000-11-30Fredrik Hübinette (Hubbe) PMOD_EXPORT struct object *low_clone(struct program *p)
5267b71995-08-09Fredrik Hübinette (Hubbe) { struct object *o;
b5dc812001-07-12Fredrik Hübinette (Hubbe)  if(!(p->flags & PROGRAM_PASS_1_DONE))
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Attempting to clone an unfinished program\n");
b1f4eb1998-01-13Fredrik Hübinette (Hubbe) 
be478c1997-08-30Henrik Grubbström (Grubba) #ifdef PROFILING p->num_clones++; #endif /* PROFILING */
648a1a2000-06-22Fredrik Hübinette (Hubbe)  o=alloc_object();
171c6b2005-03-18Henrik Grubbström (Grubba) 
a72e632010-07-01Henrik Grubbström (Grubba)  o->storage=p->storage_needed ? (char *)xcalloc(p->storage_needed, 1) : (char *)NULL;
5267b71995-08-09Fredrik Hübinette (Hubbe) 
7bf6232000-04-23Martin Stjernholm  GC_ALLOC(o);
a91a3c2006-01-24Martin Stjernholm #ifdef DO_PIKE_CLEANUP if (exit_cleanup_in_progress) {
2d6ebb2012-04-29Henrik Grubbström (Grubba)  INT_TYPE line;
a91a3c2006-01-24Martin Stjernholm  struct pike_string *file = get_program_line (p, &line); fprintf (stderr,
2d6ebb2012-04-29Henrik Grubbström (Grubba)  "Warning: Object %p created during exit cleanup from %s:%ld\n", o, file->str, (long)line);
a91a3c2006-01-24Martin Stjernholm  } #endif
1e4e5f2000-04-07Fredrik Hübinette (Hubbe) #ifdef DEBUG_MALLOC if(!debug_malloc_copy_names(o, p)) {
50edc82001-07-13Henrik Grubbström (Grubba)  struct pike_string *tmp;
2d6ebb2012-04-29Henrik Grubbström (Grubba)  INT_TYPE line;
4f985f2001-06-30Martin Stjernholm  tmp=get_program_line(p, &line);
50edc82001-07-13Henrik Grubbström (Grubba)  debug_malloc_name(o, tmp->str, line); free_string(tmp);
1e4e5f2000-04-07Fredrik Hübinette (Hubbe)  } dmalloc_set_mmap_from_template(o,p); #endif
8975b81999-10-18Fredrik Hübinette (Hubbe) 
f3c7152001-04-14Fredrik Hübinette (Hubbe)  add_ref( o->prog=p ); if(p->flags & PROGRAM_USES_PARENT) { LOW_PARENT_INFO(o,p)->parent=0; LOW_PARENT_INFO(o,p)->parent_identifier=0; }
a4033e2000-04-14Fredrik Hübinette (Hubbe)  DOUBLELINK(first_object,o);
171c6b2005-03-18Henrik Grubbström (Grubba) 
9386322011-07-21Henrik Grubbström (Grubba)  INIT_PIKE_MEMOBJ(o, T_OBJECT);
1e4e5f2000-04-07Fredrik Hübinette (Hubbe)  #ifdef PIKE_DEBUG o->program_id=p->id; #endif
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  return o; }
fa93a52008-02-28Henrik Grubbström (Grubba) #define LOW_PUSH_FRAME2(O, P) \ pike_frame=alloc_pike_frame(); \
48323c2000-07-07Henrik Grubbström (Grubba)  pike_frame->next=Pike_fp; \
88eb0e2000-04-14Henrik Grubbström (Grubba)  pike_frame->current_object=O; \
fa93a52008-02-28Henrik Grubbström (Grubba)  pike_frame->current_program=P; \
4218011999-01-31Fredrik Hübinette (Hubbe)  pike_frame->locals=0; \
fa93a52008-02-28Henrik Grubbström (Grubba)  pike_frame->num_locals=0; \
42d5b32012-01-09Henrik Grubbström (Grubba)  pike_frame->fun = FUNCTION_BUILTIN; \
fa93a52008-02-28Henrik Grubbström (Grubba)  pike_frame->pc=0; \ pike_frame->context=NULL; \ Pike_fp = pike_frame
4218011999-01-31Fredrik Hübinette (Hubbe) 
fa93a52008-02-28Henrik Grubbström (Grubba) #define LOW_PUSH_FRAME(O, P) do{ \ struct pike_frame *pike_frame; \ LOW_PUSH_FRAME2(O, P)
3ba9e22002-12-17Per Hedbor 
fa93a52008-02-28Henrik Grubbström (Grubba) #define PUSH_FRAME(O, P) \ LOW_PUSH_FRAME(O, P); \ add_ref(pike_frame->current_object); \ add_ref(pike_frame->current_program)
4218011999-01-31Fredrik Hübinette (Hubbe) 
fa93a52008-02-28Henrik Grubbström (Grubba) #define PUSH_FRAME2(O, P) do{ \ LOW_PUSH_FRAME2(O, P); \ add_ref(pike_frame->current_object); \ add_ref(pike_frame->current_program); \ }while(0)
3ba9e22002-12-17Per Hedbor 
5985c12000-10-25Fredrik Hübinette (Hubbe) #define LOW_SET_FRAME_CONTEXT(X) \ pike_frame->context=(X); \
42d5b32012-01-09Henrik Grubbström (Grubba)  pike_frame->fun = FUNCTION_BUILTIN; \
fa93a52008-02-28Henrik Grubbström (Grubba)  pike_frame->current_storage=o->storage+pike_frame->context->storage_offset
e942a72000-04-15Fredrik Hübinette (Hubbe) 
fa93a52008-02-28Henrik Grubbström (Grubba) #define SET_FRAME_CONTEXT(X) \ LOW_SET_FRAME_CONTEXT(X)
e942a72000-04-15Fredrik Hübinette (Hubbe) #define LOW_UNSET_FRAME_CONTEXT() \
fa93a52008-02-28Henrik Grubbström (Grubba)  pike_frame->context = NULL; \ pike_frame->current_storage = NULL
e942a72000-04-15Fredrik Hübinette (Hubbe) 
4218011999-01-31Fredrik Hübinette (Hubbe) #ifdef DEBUG
48323c2000-07-07Henrik Grubbström (Grubba) #define CHECK_FRAME() do { \ if(pike_frame != Pike_fp) \
5aad932002-08-15Marcus Comstedt  Pike_fatal("Frame stack out of whack.\n"); \
48323c2000-07-07Henrik Grubbström (Grubba)  } while(0)
4218011999-01-31Fredrik Hübinette (Hubbe) #else
1dec862009-08-18Stephen R. van den Berg #define CHECK_FRAME() 0
4218011999-01-31Fredrik Hübinette (Hubbe) #endif #define POP_FRAME() \
1dec862009-08-18Stephen R. van den Berg  CHECK_FRAME(); \
48323c2000-07-07Henrik Grubbström (Grubba)  Pike_fp=pike_frame->next; \
4218011999-01-31Fredrik Hübinette (Hubbe)  pike_frame->next=0; \ free_pike_frame(pike_frame); }while(0)
3ba9e22002-12-17Per Hedbor #define POP_FRAME2() \
1dec862009-08-18Stephen R. van den Berg  do{CHECK_FRAME(); \
3ba9e22002-12-17Per Hedbor  Pike_fp=pike_frame->next; \ pike_frame->next=0; \ free_pike_frame(pike_frame);}while(0)
e942a72000-04-15Fredrik Hübinette (Hubbe) #define LOW_POP_FRAME() \
48323c2000-07-07Henrik Grubbström (Grubba)  add_ref(Pike_fp->current_object); \
fa93a52008-02-28Henrik Grubbström (Grubba)  add_ref(Pike_fp->current_program); \
e942a72000-04-15Fredrik Hübinette (Hubbe)  POP_FRAME();
4218011999-01-31Fredrik Hübinette (Hubbe) 
fa8c692000-11-30Fredrik Hübinette (Hubbe) PMOD_EXPORT void call_c_initializers(struct object *o)
b1f4eb1998-01-13Fredrik Hübinette (Hubbe) { int e; struct program *p=o->prog;
3ba9e22002-12-17Per Hedbor  struct pike_frame *pike_frame=0; int frame_pushed = 0;
a72e632010-07-01Henrik Grubbström (Grubba)  /* NOTE: This function is only called for objects straight after * low_clone(), or after an explicit xcalloc(), which implies * that the storage (if any) has been zeroed. */
5267b71995-08-09Fredrik Hübinette (Hubbe)  /* clear globals and call C initializers */ for(e=p->num_inherits-1; e>=0; e--) {
3ba9e22002-12-17Per Hedbor  struct program *prog = p->inherits[e].prog; int n=(int)prog->num_variable_index; if( n )
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
3ba9e22002-12-17Per Hedbor  char *storage = o->storage+p->inherits[e].storage_offset; int q; for(q=0;q<n;q++)
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
3ba9e22002-12-17Per Hedbor  int d=prog->variable_index[q];
50ea682003-03-14Henrik Grubbström (Grubba)  if (IDENTIFIER_IS_ALIAS(prog->identifiers[d].identifier_flags)) continue;
3ba9e22002-12-17Per Hedbor  if(prog->identifiers[d].run_time_type == T_MIXED)
f945191998-04-08Fredrik Hübinette (Hubbe)  {
3ba9e22002-12-17Per Hedbor  struct svalue *s; s=(struct svalue *)(storage + prog->identifiers[d].func.offset);
017b572011-10-28Henrik Grubbström (Grubba)  SET_SVAL_TYPE(*s, T_INT);
a72e632010-07-01Henrik Grubbström (Grubba) #ifdef NEED_CUSTOM_IEEE } else if (prog->identifiers[d].run_time_type == T_FLOAT) { /* Note: In IEEE representations the value 0.0 is represented as all * zeros, and the default initialization is thus sufficient. */
3ba9e22002-12-17Per Hedbor  union anything *u; u=(union anything *)(storage + prog->identifiers[d].func.offset);
a72e632010-07-01Henrik Grubbström (Grubba)  u->float_number=0.0; #endif /* NEED_CUSTOM_IEEE */
f945191998-04-08Fredrik Hübinette (Hubbe)  }
dc79222003-03-27Martin Stjernholm  (void) debug_malloc_update_location(o, DMALLOC_NAMED_LOCATION(" clear_global"));
5267b71995-08-09Fredrik Hübinette (Hubbe)  } }
3ba9e22002-12-17Per Hedbor  if(prog->event_handler) { if( !frame_pushed ) {
fa93a52008-02-28Henrik Grubbström (Grubba)  PUSH_FRAME2(o, p);
3ba9e22002-12-17Per Hedbor  frame_pushed = 1; }
fa93a52008-02-28Henrik Grubbström (Grubba)  SET_FRAME_CONTEXT(p->inherits + e);
3ba9e22002-12-17Per Hedbor  prog->event_handler(PROG_EVENT_INIT); }
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
3ba9e22002-12-17Per Hedbor  if( frame_pushed ) POP_FRAME2();
6023ae1997-01-18Fredrik Hübinette (Hubbe) }
b5dc812001-07-12Fredrik Hübinette (Hubbe) 
cfd5322008-06-03Martin Stjernholm PMOD_EXPORT void call_prog_event(struct object *o, int event)
b5dc812001-07-12Fredrik Hübinette (Hubbe) { int e; struct program *p=o->prog;
3ba9e22002-12-17Per Hedbor  struct pike_frame *pike_frame=0; int frame_pushed = 0;
b5dc812001-07-12Fredrik Hübinette (Hubbe) 
3ba9e22002-12-17Per Hedbor  /* call event handlers */
b5dc812001-07-12Fredrik Hübinette (Hubbe)  for(e=p->num_inherits-1; e>=0; e--) {
3ba9e22002-12-17Per Hedbor  struct program *prog = p->inherits[e].prog; if(prog->event_handler) { if( !frame_pushed ) {
fa93a52008-02-28Henrik Grubbström (Grubba)  PUSH_FRAME2(o, p);
3ba9e22002-12-17Per Hedbor  frame_pushed = 1; }
fa93a52008-02-28Henrik Grubbström (Grubba)  SET_FRAME_CONTEXT(p->inherits + e);
3ba9e22002-12-17Per Hedbor  prog->event_handler(event); }
b5dc812001-07-12Fredrik Hübinette (Hubbe)  }
3ba9e22002-12-17Per Hedbor  if( frame_pushed ) POP_FRAME2();
b5dc812001-07-12Fredrik Hübinette (Hubbe) }
aa68b12001-03-19Fredrik Hübinette (Hubbe) void call_pike_initializers(struct object *o, int args)
6023ae1997-01-18Fredrik Hübinette (Hubbe) {
327c3e2001-08-30Fredrik Hübinette (Hubbe)  ptrdiff_t fun; struct program *p=o->prog; if(!p) return;
6d87ec2007-12-18Henrik Grubbström (Grubba)  STACK_LEVEL_START(args);
327c3e2001-08-30Fredrik Hübinette (Hubbe)  fun=FIND_LFUN(p, LFUN___INIT); if(fun!=-1) { apply_low(o,fun,0);
72b0812013-06-11Per Hedbor  Pike_sp--;
327c3e2001-08-30Fredrik Hübinette (Hubbe)  }
6d87ec2007-12-18Henrik Grubbström (Grubba)  STACK_LEVEL_CHECK(args);
327c3e2001-08-30Fredrik Hübinette (Hubbe)  fun=FIND_LFUN(p, LFUN_CREATE); if(fun!=-1) { apply_low(o,fun,args); pop_stack();
6d87ec2007-12-18Henrik Grubbström (Grubba)  } else { pop_n_elems(args);
327c3e2001-08-30Fredrik Hübinette (Hubbe)  }
6d87ec2007-12-18Henrik Grubbström (Grubba)  STACK_LEVEL_DONE(0);
5207bb1997-02-06Fredrik Hübinette (Hubbe) }
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void do_free_object(struct object *o)
5207bb1997-02-06Fredrik Hübinette (Hubbe) {
65b6732000-07-07Martin Stjernholm  if (o) free_object(o);
3c0c281998-01-26Fredrik Hübinette (Hubbe) }
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT struct object *debug_clone_object(struct program *p, int args)
3c0c281998-01-26Fredrik Hübinette (Hubbe) { ONERROR tmp;
0894392000-03-09Fredrik Hübinette (Hubbe)  struct object *o;
22d7992001-06-23Fredrik Hübinette (Hubbe)  if(p->flags & PROGRAM_NEEDS_PARENT)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Parent lost, cannot clone program.\n");
0894392000-03-09Fredrik Hübinette (Hubbe) 
4bb39c2001-11-08Fredrik Hübinette (Hubbe)  if(!(p->flags & PROGRAM_PASS_1_DONE))
b5dc812001-07-12Fredrik Hübinette (Hubbe)  Pike_error("Attempting to clone an unfinished program\n");
0894392000-03-09Fredrik Hübinette (Hubbe)  o=low_clone(p);
6d87ec2007-12-18Henrik Grubbström (Grubba)  if (!args) { push_object(o); } else { SET_ONERROR(tmp, do_free_object, o); debug_malloc_touch(o); }
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  call_c_initializers(o);
fdd2bc1999-09-28Fredrik Hübinette (Hubbe)  debug_malloc_touch(o);
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  call_pike_initializers(o,args);
6657a51999-10-21Fredrik Hübinette (Hubbe)  debug_malloc_touch(o);
648a1a2000-06-22Fredrik Hübinette (Hubbe)  debug_malloc_touch(o->storage);
6d87ec2007-12-18Henrik Grubbström (Grubba)  if (!args) {
15e6012008-04-18Henrik Grubbström (Grubba)  /* Pop o from the stack. */
6d87ec2007-12-18Henrik Grubbström (Grubba)  Pike_sp--; } else { UNSET_ONERROR(tmp); }
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  return o; }
055c1f2003-02-15Henrik Grubbström (Grubba) /* Clone and initialize an object, but do not call the pike initializers. * * WARNING: Only use this function if you know what you are doing... */ PMOD_EXPORT struct object *fast_clone_object(struct program *p)
0957531999-10-25Fredrik Hübinette (Hubbe) { struct object *o=low_clone(p);
6d87ec2007-12-18Henrik Grubbström (Grubba)  push_object(o);
0957531999-10-25Fredrik Hübinette (Hubbe)  call_c_initializers(o);
6d87ec2007-12-18Henrik Grubbström (Grubba)  Pike_sp--;
0957531999-10-25Fredrik Hübinette (Hubbe)  debug_malloc_touch(o);
648a1a2000-06-22Fredrik Hübinette (Hubbe)  debug_malloc_touch(o->storage);
0957531999-10-25Fredrik Hübinette (Hubbe)  return o; }
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT struct object *parent_clone_object(struct program *p,
c0fb642000-08-10Henrik Grubbström (Grubba)  struct object *parent, ptrdiff_t parent_identifier, int args)
b1f4eb1998-01-13Fredrik Hübinette (Hubbe) {
3c0c281998-01-26Fredrik Hübinette (Hubbe)  ONERROR tmp;
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  struct object *o=low_clone(p);
6d87ec2007-12-18Henrik Grubbström (Grubba)  if (!args) { push_object(o); } else { SET_ONERROR(tmp, do_free_object, o); debug_malloc_touch(o); }
1c1c5e2001-04-08Fredrik Hübinette (Hubbe) 
4bb39c2001-11-08Fredrik Hübinette (Hubbe)  if(!(p->flags & PROGRAM_PASS_1_DONE))
b5dc812001-07-12Fredrik Hübinette (Hubbe)  Pike_error("Attempting to clone an unfinished program\n");
1c1c5e2001-04-08Fredrik Hübinette (Hubbe)  if(p->flags & PROGRAM_USES_PARENT)
f3c7152001-04-14Fredrik Hübinette (Hubbe)  { add_ref( PARENT_INFO(o)->parent=parent ); PARENT_INFO(o)->parent_identifier = DO_NOT_WARN((INT32)parent_identifier); }
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  call_c_initializers(o); call_pike_initializers(o,args);
6d87ec2007-12-18Henrik Grubbström (Grubba)  if (!args) { Pike_sp--; } else { UNSET_ONERROR(tmp); }
5267b71995-08-09Fredrik Hübinette (Hubbe)  return o; }
7aa0862002-01-11Martin Stjernholm PMOD_EXPORT struct object *clone_object_from_object(struct object *o, int args) { if (o->prog->flags & PROGRAM_USES_PARENT) return parent_clone_object(o->prog, PARENT_INFO(o)->parent, PARENT_INFO(o)->parent_identifier, args); else return clone_object(o->prog, args); }
b5dc812001-07-12Fredrik Hübinette (Hubbe) /* BEWARE: This function does not call create() or __INIT() */ struct object *decode_value_clone_object(struct svalue *prog) { struct object *o, *parent; ONERROR tmp; INT32 parent_identifier; struct program *p=program_from_svalue(prog);
509f212003-06-03Martin Stjernholm  if(!p) return NULL;
b5dc812001-07-12Fredrik Hübinette (Hubbe)  o=low_clone(p); SET_ONERROR(tmp, do_free_object, o); debug_malloc_touch(o);
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(*prog) == T_FUNCTION)
b5dc812001-07-12Fredrik Hübinette (Hubbe)  { parent=prog->u.object;
017b572011-10-28Henrik Grubbström (Grubba)  parent_identifier = SUBTYPEOF(*prog);
b5dc812001-07-12Fredrik Hübinette (Hubbe)  }else{ parent=0; parent_identifier=0; } if(p->flags & PROGRAM_USES_PARENT) { PARENT_INFO(o)->parent=parent; if(parent) add_ref(parent); PARENT_INFO(o)->parent_identifier = DO_NOT_WARN((INT32)parent_identifier); } call_c_initializers(o); UNSET_ONERROR(tmp); return o; }
8941812005-01-11Martin Nilsson static struct pike_string *low_read_file(const char *file)
05590d1998-04-23Fredrik Hübinette (Hubbe) { struct pike_string *s;
1abbfb2006-07-05Martin Stjernholm  PIKE_OFF_T len;
9a49cb1999-06-19Fredrik Hübinette (Hubbe)  FD f;
81a57e2000-08-20Henrik Grubbström (Grubba) 
b8a1482013-03-17Chris Angelico  while((f = fd_open(file,fd_RDONLY|fd_BINARY,0666)) <0 && errno==EINTR)
700dac2002-02-05Martin Stjernholm  check_threads_etc();
81a57e2000-08-20Henrik Grubbström (Grubba)  if(f >= 0)
05590d1998-04-23Fredrik Hübinette (Hubbe)  {
e3fde92013-03-16Henrik Grubbström (Grubba)  PIKE_OFF_T tmp, pos = 0;
9a49cb1999-06-19Fredrik Hübinette (Hubbe) 
81a57e2000-08-20Henrik Grubbström (Grubba)  len = fd_lseek(f, 0, SEEK_END); fd_lseek(f, 0, SEEK_SET);
1abbfb2006-07-05Martin Stjernholm  if (len > MAX_INT32) Pike_fatal ("low_read_file(%s): File too large: %"PRINTPIKEOFFT"d b.\n", file, len); s = begin_shared_string (DO_NOT_WARN ((ptrdiff_t) len));
9a49cb1999-06-19Fredrik Hübinette (Hubbe)  while(pos<len) {
1abbfb2006-07-05Martin Stjernholm  tmp = fd_read(f,s->str+pos, DO_NOT_WARN ((ptrdiff_t) len) - pos);
2c6a4a2003-07-21Henrik Grubbström (Grubba)  if(tmp<=0)
9a49cb1999-06-19Fredrik Hübinette (Hubbe)  {
2c6a4a2003-07-21Henrik Grubbström (Grubba)  if (tmp < 0) { if(errno==EINTR) { check_threads_etc(); continue; } Pike_fatal("low_read_file(%s) failed, errno=%d\n",file,errno);
700dac2002-02-05Martin Stjernholm  }
2d76f22005-05-20Martin Stjernholm  Pike_fatal("low_read_file(%s) failed, short read: "
1abbfb2006-07-05Martin Stjernholm  "%"PRINTPIKEOFFT"d < %"PRINTPIKEOFFT"d\n",
2c6a4a2003-07-21Henrik Grubbström (Grubba)  file, pos, len);
9a49cb1999-06-19Fredrik Hübinette (Hubbe)  } pos+=tmp; } fd_close(f);
05590d1998-04-23Fredrik Hübinette (Hubbe)  return end_shared_string(s); } return 0; }
b1f4eb1998-01-13Fredrik Hübinette (Hubbe) 
74dfe82012-12-30Jonas Walldén static void get_master_cleanup (void *UNUSED(dummy))
aac8822003-08-06Martin Stjernholm { if (master_object) { free_object (master_object); master_object = 0; } }
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT struct object *get_master(void)
5267b71995-08-09Fredrik Hübinette (Hubbe) { static int inside=0; if(master_object && master_object->prog) return master_object;
7a12332003-07-16Martin Stjernholm  if(inside || master_is_cleaned_up) return 0;
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(master_object) { free_object(master_object); master_object=0; } inside = 1;
6023ae1997-01-18Fredrik Hübinette (Hubbe) 
eff2b02001-07-03Henrik Grubbström (Grubba)  /* fprintf(stderr, "Need a new master object...\n"); */
6023ae1997-01-18Fredrik Hübinette (Hubbe)  if(!master_program) {
c2f1a01999-11-16Henrik Grubbström (Grubba)  struct pike_string *s;
d50a391999-08-14Fredrik Hübinette (Hubbe)  char *tmp;
40962a2003-03-27Martin Stjernholm  PIKE_STAT_T stat_buf;
61f3851999-03-11Henrik Grubbström (Grubba) 
8e6c0c2002-01-27Martin Stjernholm  if(!get_builtin_constants() || !simple_mapping_string_lookup(get_builtin_constants(),
d50a391999-08-14Fredrik Hübinette (Hubbe)  "_static_modules")) {
3699a42008-04-25Henrik Grubbström (Grubba)  inside = 0;
6d87ec2007-12-18Henrik Grubbström (Grubba)  /* fprintf(stderr, "Builtin_constants: %p\n", get_builtin_constants()); */
8e6c0c2002-01-27Martin Stjernholm  /* fprintf(stderr,"Cannot load master object yet!\n"); */ return 0;
d50a391999-08-14Fredrik Hübinette (Hubbe)  }
eff2b02001-07-03Henrik Grubbström (Grubba)  /* fprintf(stderr, "Master file: \"%s\"\n", master_file); */
d50a391999-08-14Fredrik Hübinette (Hubbe)  tmp=xalloc(strlen(master_file)+3);
05590d1998-04-23Fredrik Hübinette (Hubbe)  MEMCPY(tmp, master_file, strlen(master_file)+1); strcat(tmp,".o");
61f3851999-03-11Henrik Grubbström (Grubba)  s = NULL;
b602dc2000-06-16Fredrik Hübinette (Hubbe)  if (!fd_stat(tmp, &stat_buf)) {
1abbfb2006-07-05Martin Stjernholm  time_t ts1 = stat_buf.st_mtime; time_t ts2 = 0;
61f3851999-03-11Henrik Grubbström (Grubba) 
b602dc2000-06-16Fredrik Hübinette (Hubbe)  if (!fd_stat(master_file, &stat_buf)) {
61f3851999-03-11Henrik Grubbström (Grubba)  ts2 = stat_buf.st_mtime; }
4bb39c2001-11-08Fredrik Hübinette (Hubbe)  if (ts1 >= ts2) {
c2f1a01999-11-16Henrik Grubbström (Grubba)  s = low_read_file(tmp);
61f3851999-03-11Henrik Grubbström (Grubba)  } }
05590d1998-04-23Fredrik Hübinette (Hubbe)  free(tmp); if(s) { JMP_BUF tmp;
c2f1a01999-11-16Henrik Grubbström (Grubba) 
eff2b02001-07-03Henrik Grubbström (Grubba)  /* fprintf(stderr, "Trying precompiled file \"%s.o\"...\n", * master_file); */
c2f1a01999-11-16Henrik Grubbström (Grubba)  /* Moved here to avoid gcc warning: "might be clobbered". */ push_string(s); push_int(0);
3601d32002-11-23Martin Stjernholm  if(SETJMP_SP(tmp, 2))
05590d1998-04-23Fredrik Hübinette (Hubbe)  {
45ee5d1999-02-10Fredrik Hübinette (Hubbe) #ifdef DEBUG
e8e2532009-08-25Henrik Grubbström (Grubba)  if(d_flag) { struct svalue sval; /* Note: Save the svalue before attempting to describe it, * since it might get overwritten... */ assign_svalue_no_free(&sval, &throw_value); debug_describe_svalue(&sval); free_svalue(&sval); }
45ee5d1999-02-10Fredrik Hübinette (Hubbe) #endif
05590d1998-04-23Fredrik Hübinette (Hubbe)  /* do nothing */ UNSETJMP(tmp);
c1b8f02001-07-02Martin Stjernholm  free_svalue(&throw_value);
1ab4ac2008-01-26Martin Stjernholm  mark_free_svalue (&throw_value);
05590d1998-04-23Fredrik Hübinette (Hubbe)  }else{ f_decode_value(2);
c857761999-03-16Fredrik Hübinette (Hubbe)  UNSETJMP(tmp);
b1f4eb1998-01-13Fredrik Hübinette (Hubbe) 
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(sp[-1]) == T_PROGRAM)
05590d1998-04-23Fredrik Hübinette (Hubbe)  goto compiled;
b1f4eb1998-01-13Fredrik Hübinette (Hubbe) 
05590d1998-04-23Fredrik Hübinette (Hubbe)  pop_stack();
c857761999-03-16Fredrik Hübinette (Hubbe) 
05590d1998-04-23Fredrik Hübinette (Hubbe)  }
45ee5d1999-02-10Fredrik Hübinette (Hubbe) #ifdef DEBUG if(d_flag) fprintf(stderr,"Failed to import dumped master!\n"); #endif
05590d1998-04-23Fredrik Hübinette (Hubbe)  }
eff2b02001-07-03Henrik Grubbström (Grubba)  /* fprintf(stderr, "Reading master: \"%s\"...\n", master_file); */
c2f1a01999-11-16Henrik Grubbström (Grubba)  s=low_read_file(master_file); if(s)
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  {
c2f1a01999-11-16Henrik Grubbström (Grubba)  push_string(s);
dc7cc91998-01-14Fredrik Hübinette (Hubbe)  push_text(master_file);
eff2b02001-07-03Henrik Grubbström (Grubba)  /* fprintf(stderr, "Calling cpp()...\n"); */
dc7cc91998-01-14Fredrik Hübinette (Hubbe)  f_cpp(2);
eff2b02001-07-03Henrik Grubbström (Grubba)  /* fprintf(stderr, "Calling compile()...\n"); */
dc7cc91998-01-14Fredrik Hübinette (Hubbe)  f_compile(1);
05590d1998-04-23Fredrik Hübinette (Hubbe)  compiled:
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(sp[-1]) != T_PROGRAM)
dc7cc91998-01-14Fredrik Hübinette (Hubbe)  { pop_stack(); return 0; } master_program=sp[-1].u.program; sp--;
5d35781999-10-24Henrik Grubbström (Grubba)  dmalloc_touch_svalue(sp);
dc7cc91998-01-14Fredrik Hübinette (Hubbe)  }else{
db14502008-05-27Henrik Grubbström (Grubba)  throw_error_object(fast_clone_object(master_load_error_program), 0, 0, 0, "Couldn't load master program from %s.\n", master_file);
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  }
6023ae1997-01-18Fredrik Hübinette (Hubbe)  }
eff2b02001-07-03Henrik Grubbström (Grubba) 
aac8822003-08-06Martin Stjernholm  {
b01e7e2010-07-29Martin Stjernholm  int f;
aac8822003-08-06Martin Stjernholm  ONERROR uwp;
eff2b02001-07-03Henrik Grubbström (Grubba) 
aac8822003-08-06Martin Stjernholm  /* fprintf(stderr, "Cloning master...\n"); */
6023ae1997-01-18Fredrik Hübinette (Hubbe) 
aac8822003-08-06Martin Stjernholm  master_object=low_clone(master_program); debug_malloc_touch(master_object); debug_malloc_touch(master_object->storage);
eff2b02001-07-03Henrik Grubbström (Grubba) 
aac8822003-08-06Martin Stjernholm  /* Make sure master_object doesn't point to a broken master. */ SET_ONERROR (uwp, get_master_cleanup, NULL); /* fprintf(stderr, "Initializing master...\n"); */ call_c_initializers(master_object); call_pike_initializers(master_object,0);
b01e7e2010-07-29Martin Stjernholm  f = find_identifier ("is_pike_master", master_program); if (f >= 0)
b23ce12012-04-29Henrik Grubbström (Grubba)  object_low_set_index (master_object, f, (struct svalue *)&svalue_int_one);
b01e7e2010-07-29Martin Stjernholm 
aac8822003-08-06Martin Stjernholm  /* fprintf(stderr, "Master loaded.\n"); */ UNSET_ONERROR (uwp); }
eff2b02001-07-03Henrik Grubbström (Grubba) 
5267b71995-08-09Fredrik Hübinette (Hubbe)  inside = 0; return master_object; }
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT struct object *debug_master(void)
5267b71995-08-09Fredrik Hübinette (Hubbe) { struct object *o; o=get_master();
5aad932002-08-15Marcus Comstedt  if(!o) Pike_fatal("Couldn't load master object.\n");
5267b71995-08-09Fredrik Hübinette (Hubbe)  return o; }
fc2c831999-04-01Fredrik Hübinette (Hubbe) struct destroy_called_mark
5267b71995-08-09Fredrik Hübinette (Hubbe) {
fc2c831999-04-01Fredrik Hübinette (Hubbe)  struct destroy_called_mark *next; void *data;
2a52ff2000-10-01Fredrik Hübinette (Hubbe)  struct program *p; /* for magic */
fc2c831999-04-01Fredrik Hübinette (Hubbe) };
5267b71995-08-09Fredrik Hübinette (Hubbe) 
fc2c831999-04-01Fredrik Hübinette (Hubbe) PTR_HASH_ALLOC(destroy_called_mark,128)
5683de1995-11-06Fredrik Hübinette (Hubbe) 
2a52ff2000-10-01Fredrik Hübinette (Hubbe) PMOD_EXPORT struct program *get_program_for_object_being_destructed(struct object * o) { struct destroy_called_mark * tmp; if(( tmp = find_destroy_called_mark(o))) return tmp->p; return 0; }
09f2882005-02-09Martin Stjernholm static void call_destroy(struct object *o, enum object_destruct_reason reason)
fc2c831999-04-01Fredrik Hübinette (Hubbe) {
766bc82004-10-16Marcus Agehall  volatile int e;
3ba9e22002-12-17Per Hedbor 
54717e2001-06-28Fredrik Hübinette (Hubbe)  debug_malloc_touch(o);
e2d9e62000-06-10Martin Stjernholm  if(!o || !o->prog) { #ifdef GC_VERBOSE if (Pike_in_gc > GC_PASS_PREPARE) fprintf(stderr, "| Not calling destroy() in " "destructed %p with %d refs.\n", o, o->refs); #endif return; /* Object already destructed */ }
5683de1995-11-06Fredrik Hübinette (Hubbe) 
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  e=FIND_LFUN(o->prog,LFUN_DESTROY);
e2d9e62000-06-10Martin Stjernholm  if(e != -1 #ifdef DO_PIKE_CLEANUP
48323c2000-07-07Henrik Grubbström (Grubba)  && Pike_interpreter.evaluator_stack
e2d9e62000-06-10Martin Stjernholm #endif
4bb39c2001-11-08Fredrik Hübinette (Hubbe)  && (o->prog->flags & PROGRAM_FINISHED))
e3a26e1996-06-21Fredrik Hübinette (Hubbe)  {
e2d9e62000-06-10Martin Stjernholm #ifdef PIKE_DEBUG
da49a22001-06-11Martin Stjernholm  if(Pike_in_gc > GC_PASS_PREPARE && Pike_in_gc < GC_PASS_FREE)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Calling destroy() inside gc.\n");
e2d9e62000-06-10Martin Stjernholm #endif
e921e72008-01-24Henrik Grubbström (Grubba)  if(check_destroy_called_mark_semaphore(o))
ba35bf1998-04-14Fredrik Hübinette (Hubbe)  {
9a5d082004-03-16Martin Stjernholm  JMP_BUF jmp;
e2d9e62000-06-10Martin Stjernholm #ifdef GC_VERBOSE if (Pike_in_gc > GC_PASS_PREPARE) fprintf(stderr, "| Calling destroy() in %p with %d refs.\n", o, o->refs); #endif
9a5d082004-03-16Martin Stjernholm  free_svalue (&throw_value);
1ab4ac2008-01-26Martin Stjernholm  mark_free_svalue (&throw_value);
9a5d082004-03-16Martin Stjernholm  if (SETJMP (jmp)) { UNSETJMP (jmp); if (gc_destruct_everything) { struct svalue err; move_svalue (&err, &throw_value);
1ab4ac2008-01-26Martin Stjernholm  mark_free_svalue (&throw_value);
9a5d082004-03-16Martin Stjernholm  if (!SETJMP (jmp)) { push_svalue (&err); push_int (0); push_text ("Got error during final cleanup:\n"); push_svalue (&err); push_int (0); o_index(); f_add (2); f_index_assign (3); pop_stack(); } UNSETJMP (jmp); move_svalue (&throw_value, &err); } call_handle_error(); } else {
09f2882005-02-09Martin Stjernholm  push_int (reason); apply_low(o, e, 1);
9a5d082004-03-16Martin Stjernholm  pop_stack(); UNSETJMP (jmp); }
e2d9e62000-06-10Martin Stjernholm #ifdef GC_VERBOSE if (Pike_in_gc > GC_PASS_PREPARE) fprintf(stderr, "| Called destroy() in %p with %d refs.\n", o, o->refs); #endif
ba35bf1998-04-14Fredrik Hübinette (Hubbe)  }
e3a26e1996-06-21Fredrik Hübinette (Hubbe)  }
e2d9e62000-06-10Martin Stjernholm #ifdef GC_VERBOSE else if (Pike_in_gc > GC_PASS_PREPARE) fprintf(stderr, "| No destroy() to call in %p with %d refs.\n", o, o->refs); #endif
fc2c831999-04-01Fredrik Hübinette (Hubbe) }
72b0812013-06-11Per Hedbor static int object_has_destroy( struct object *o ) { return QUICK_FIND_LFUN( o->prog, LFUN_DESTROY ) != -1; }
2a52ff2000-10-01Fredrik Hübinette (Hubbe) 
09f2882005-02-09Martin Stjernholm PMOD_EXPORT void destruct_object (struct object *o, enum object_destruct_reason reason)
fc2c831999-04-01Fredrik Hübinette (Hubbe) { int e; struct program *p;
3ba9e22002-12-17Per Hedbor  struct pike_frame *pike_frame=0;
72b0812013-06-11Per Hedbor  int frame_pushed = 0, destroy_called = 0;
fc2c831999-04-01Fredrik Hübinette (Hubbe)  #ifdef PIKE_DEBUG
ec56182001-02-03Martin Stjernholm  ONERROR uwp;
6b11412003-11-18Henrik Grubbström (Grubba)  fatal_check_c_stack(8192);
ec56182001-02-03Martin Stjernholm  SET_ONERROR(uwp, fatal_on_error, "Shouldn't get an exception in destruct().\n");
fc2c831999-04-01Fredrik Hübinette (Hubbe)  if(d_flag > 20) do_debug();
45c1562010-04-10Martin Stjernholm  if (Pike_in_gc >= GC_PASS_PRETOUCH && Pike_in_gc < GC_PASS_FREE) gc_fatal (o, 1, "Destructing objects is not allowed inside the gc.\n");
e2d9e62000-06-10Martin Stjernholm #endif
45c1562010-04-10Martin Stjernholm 
e2d9e62000-06-10Martin Stjernholm #ifdef GC_VERBOSE
d9d6f02001-06-30Martin Stjernholm  if (Pike_in_gc > GC_PASS_PREPARE) { fprintf(stderr, "| Destructing %p with %d refs", o, o->refs); if (o->prog) { INT32 line;
50edc82001-07-13Henrik Grubbström (Grubba)  struct pike_string *file = get_program_line (o->prog, &line); fprintf(stderr, ", prog %s:%d\n", file->str, line); free_string(file);
d9d6f02001-06-30Martin Stjernholm  } else fputs(", is destructed\n", stderr); }
fc2c831999-04-01Fredrik Hübinette (Hubbe) #endif
c4ff7f2013-06-12Arne Goedeke  if( !(p = o->prog) ) { #ifdef PIKE_DEBUG UNSET_ONERROR(uwp); #endif
72b0812013-06-11Per Hedbor  return;
c4ff7f2013-06-12Arne Goedeke  }
a267382002-12-17Per Hedbor  add_ref( o );
72b0812013-06-11Per Hedbor  if( object_has_destroy( o ) )
5683de1995-11-06Fredrik Hübinette (Hubbe)  {
72b0812013-06-11Per Hedbor  call_destroy(o, reason); destroy_called = 1; /* destructed in destroy() */ if(!(p=o->prog)) { free_object(o);
ec56182001-02-03Martin Stjernholm #ifdef PIKE_DEBUG
72b0812013-06-11Per Hedbor  UNSET_ONERROR(uwp);
ec56182001-02-03Martin Stjernholm #endif
72b0812013-06-11Per Hedbor  return; } get_destroy_called_mark(o)->p=p;
5683de1995-11-06Fredrik Hübinette (Hubbe)  }
26dc072000-04-06Fredrik Hübinette (Hubbe)  debug_malloc_touch(o);
648a1a2000-06-22Fredrik Hübinette (Hubbe)  debug_malloc_touch(o->storage);
c4a8bc2003-03-30Martin Stjernholm  debug_malloc_touch(p);
5267b71995-08-09Fredrik Hübinette (Hubbe)  o->prog=0;
e2d9e62000-06-10Martin Stjernholm #ifdef GC_VERBOSE if (Pike_in_gc > GC_PASS_PREPARE) fprintf(stderr, "| Zapping references in %p with %d refs.\n", o, o->refs); #endif
5267b71995-08-09Fredrik Hübinette (Hubbe)  /* free globals and call C de-initializers */ for(e=p->num_inherits-1; e>=0; e--) {
05590d1998-04-23Fredrik Hübinette (Hubbe)  int q;
3ba9e22002-12-17Per Hedbor  struct program *prog = p->inherits[e].prog; char *storage = o->storage+p->inherits[e].storage_offset;
72b0812013-06-11Per Hedbor 
3ba9e22002-12-17Per Hedbor  if(prog->event_handler)
26dc072000-04-06Fredrik Hübinette (Hubbe)  {
3ba9e22002-12-17Per Hedbor  if( !frame_pushed ) {
fa93a52008-02-28Henrik Grubbström (Grubba)  PUSH_FRAME2(o, p);
3ba9e22002-12-17Per Hedbor  frame_pushed = 1; }
fa93a52008-02-28Henrik Grubbström (Grubba)  SET_FRAME_CONTEXT(p->inherits + e);
3ba9e22002-12-17Per Hedbor  prog->event_handler(PROG_EVENT_EXIT);
26dc072000-04-06Fredrik Hübinette (Hubbe)  }
1ab7c61999-04-08Fredrik Hübinette (Hubbe) 
3ba9e22002-12-17Per Hedbor  for(q=0;q<(int)prog->num_variable_index;q++)
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
3ba9e22002-12-17Per Hedbor  int d=prog->variable_index[q];
e0d6f52003-02-13Martin Stjernholm  struct identifier *id = prog->identifiers + d;
50ea682003-03-14Henrik Grubbström (Grubba)  int identifier_flags = id->identifier_flags;
e0d6f52003-02-13Martin Stjernholm  int rtt = id->run_time_type;
eff2b02001-07-03Henrik Grubbström (Grubba) 
50ea682003-03-14Henrik Grubbström (Grubba)  if (IDENTIFIER_IS_ALIAS(identifier_flags))
eff2b02001-07-03Henrik Grubbström (Grubba)  continue;
50ea682003-03-14Henrik Grubbström (Grubba) 
e0d6f52003-02-13Martin Stjernholm  if(rtt == T_MIXED)
5267b71995-08-09Fredrik Hübinette (Hubbe)  { struct svalue *s;
e0d6f52003-02-13Martin Stjernholm  s=(struct svalue *)(storage + id->func.offset);
2c266e2003-02-15Martin Stjernholm  dmalloc_touch_svalue(s);
017b572011-10-28Henrik Grubbström (Grubba)  if ((TYPEOF(*s) != T_OBJECT && TYPEOF(*s) != T_FUNCTION) ||
50ea682003-03-14Henrik Grubbström (Grubba)  s->u.object != o || !(identifier_flags & IDENTIFIER_NO_THIS_REF)) {
dc79222003-03-27Martin Stjernholm  (void) debug_malloc_update_location(o, DMALLOC_NAMED_LOCATION(" free_global"));
8d4faf2003-02-10Martin Stjernholm  free_svalue(s);
50ea682003-03-14Henrik Grubbström (Grubba) #ifdef DEBUG_MALLOC } else {
dc79222003-03-27Martin Stjernholm  (void) debug_malloc_update_location(o, DMALLOC_NAMED_LOCATION(" skip_global"));
50ea682003-03-14Henrik Grubbström (Grubba)  dmalloc_touch_svalue(s); #endif /* DEBUG_MALLOC */ }
2e1a6a2008-05-29Henrik Grubbström (Grubba)  } else if ((rtt != PIKE_T_GET_SET) && (rtt != PIKE_T_FREE)) {
5267b71995-08-09Fredrik Hübinette (Hubbe)  union anything *u;
e0d6f52003-02-13Martin Stjernholm  u=(union anything *)(storage + id->func.offset);
2c266e2003-02-15Martin Stjernholm #ifdef DEBUG_MALLOC
4a93e82013-06-11Henrik Grubbström (Grubba)  if (REFCOUNTED_TYPE(rtt)) {debug_malloc_touch(u->refs);}
2c266e2003-02-15Martin Stjernholm #endif
e0d6f52003-02-13Martin Stjernholm  if (rtt != T_OBJECT || u->object != o ||
50ea682003-03-14Henrik Grubbström (Grubba)  !(identifier_flags & IDENTIFIER_NO_THIS_REF)) {
dc79222003-03-27Martin Stjernholm  (void) debug_malloc_update_location(o, DMALLOC_NAMED_LOCATION(" free_global"));
e0d6f52003-02-13Martin Stjernholm  free_short_svalue(u, rtt);
50ea682003-03-14Henrik Grubbström (Grubba) #ifdef DEBUG_MALLOC } else {
dc79222003-03-27Martin Stjernholm  (void) debug_malloc_update_location(o, DMALLOC_NAMED_LOCATION(" skip_global"));
50ea682003-03-14Henrik Grubbström (Grubba) #endif /* DEBUG_MALLOC */ }
1e4e5f2000-04-07Fredrik Hübinette (Hubbe)  DO_IF_DMALLOC(u->refs=(void *)-1);
5267b71995-08-09Fredrik Hübinette (Hubbe)  } } }
8efc6a2000-04-06Fredrik Hübinette (Hubbe)  debug_malloc_touch(o);
648a1a2000-06-22Fredrik Hübinette (Hubbe)  debug_malloc_touch(o->storage);
f3c7152001-04-14Fredrik Hübinette (Hubbe)  if(p->flags & PROGRAM_USES_PARENT)
20f7a02000-03-20Fredrik Hübinette (Hubbe)  {
f3c7152001-04-14Fredrik Hübinette (Hubbe)  if(LOW_PARENT_INFO(o,p)->parent) {
54717e2001-06-28Fredrik Hübinette (Hubbe)  debug_malloc_touch(o);
f3c7152001-04-14Fredrik Hübinette (Hubbe)  /* fprintf(stderr, "destruct(): Zapping parent.\n"); */ free_object(LOW_PARENT_INFO(o,p)->parent); LOW_PARENT_INFO(o,p)->parent=0; }
20f7a02000-03-20Fredrik Hübinette (Hubbe)  }
3ba9e22002-12-17Per Hedbor  if( frame_pushed ) POP_FRAME2();
e2d9e62000-06-10Martin Stjernholm 
a267382002-12-17Per Hedbor  free_object( o );
5267b71995-08-09Fredrik Hübinette (Hubbe)  free_program(p);
72b0812013-06-11Per Hedbor  if( destroy_called ) remove_destroy_called_mark(o);
5267b71995-08-09Fredrik Hübinette (Hubbe) 
ec56182001-02-03Martin Stjernholm #ifdef PIKE_DEBUG UNSET_ONERROR(uwp); #endif
1ab7c61999-04-08Fredrik Hübinette (Hubbe) }
06983f1996-09-22Fredrik Hübinette (Hubbe) 
dda7592008-07-24Martin Stjernholm struct object *objects_to_destruct = NULL; static struct callback *destruct_object_evaluator_callback = NULL;
5267b71995-08-09Fredrik Hübinette (Hubbe) 
06983f1996-09-22Fredrik Hübinette (Hubbe) /* This function destructs the objects that are scheduled to be
648a1a2000-06-22Fredrik Hübinette (Hubbe)  * destructed by schedule_really_free_object. It links the object back into the
06983f1996-09-22Fredrik Hübinette (Hubbe)  * list of objects first. Adds a reference, destructs it and then frees it. */
2ac9502001-08-14Fredrik Hübinette (Hubbe) void low_destruct_objects_to_destruct(void)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
aec5af2001-01-22Martin Stjernholm  struct object *o, *next;
a29e021996-10-15Fredrik Hübinette (Hubbe) 
762a402000-08-03Martin Stjernholm #ifdef PIKE_DEBUG
da49a22001-06-11Martin Stjernholm  if (Pike_in_gc > GC_PASS_PREPARE && Pike_in_gc < GC_PASS_FREE)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Can't meddle with the object link list in gc pass %d.\n", Pike_in_gc);
762a402000-08-03Martin Stjernholm #endif
87c7f92000-04-19Martin Stjernholm 
aec5af2001-01-22Martin Stjernholm  /* We unlink the list from objects_to_destruct before processing it, * to avoid that reentrant calls to this function go through all * objects instead of just the newly added ones. This way we avoid * extensive recursion in this function and also avoid destructing
7c2e072010-04-11Martin Stjernholm  * the objects arbitrarily late. * * Note that we might start a gc during this, but since the unlinked * objects have no refs, the gc never encounters them. */
aec5af2001-01-22Martin Stjernholm  while (objects_to_destruct) { o = objects_to_destruct, objects_to_destruct = 0;
dda7592008-07-24Martin Stjernholm  /* When we remove the object list from objects_to_destruct, it * becomes invisible to gc_touch_all_objects (and other list walk * functions), so the object count it returns would be wrong. We * therefore use this hack to avoid complaining about it in the * gc. */ got_unlinked_things++;
aec5af2001-01-22Martin Stjernholm  do {
e2d9e62000-06-10Martin Stjernholm #ifdef GC_VERBOSE
aec5af2001-01-22Martin Stjernholm  if (Pike_in_gc > GC_PASS_PREPARE) fprintf(stderr, "| Destructing %p on objects_to_destruct.\n", o);
e2d9e62000-06-10Martin Stjernholm #endif
aec5af2001-01-22Martin Stjernholm  next = o->next;
54717e2001-06-28Fredrik Hübinette (Hubbe)  debug_malloc_touch(o); debug_malloc_touch(next);
7bf6232000-04-23Martin Stjernholm 
aec5af2001-01-22Martin Stjernholm  /* Link object back to list of objects */ DOUBLELINK(first_object,o);
e2d9e62000-06-10Martin Stjernholm 
aec5af2001-01-22Martin Stjernholm  /* call destroy, keep one ref */ add_ref(o);
09f2882005-02-09Martin Stjernholm  destruct_object (o, DESTRUCT_NO_REFS);
aec5af2001-01-22Martin Stjernholm  free_object(o); } while ((o = next));
dda7592008-07-24Martin Stjernholm  got_unlinked_things--;
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
2ac9502001-08-14Fredrik Hübinette (Hubbe) }
a4033e2000-04-14Fredrik Hübinette (Hubbe) 
2ac9502001-08-14Fredrik Hübinette (Hubbe) void destruct_objects_to_destruct_cb(void) { low_destruct_objects_to_destruct();
7f9b4c2000-04-19Martin Stjernholm  if(destruct_object_evaluator_callback) { remove_callback(destruct_object_evaluator_callback); destruct_object_evaluator_callback=0; }
a29e021996-10-15Fredrik Hübinette (Hubbe) }
648a1a2000-06-22Fredrik Hübinette (Hubbe) /* schedule_really_free_object:
a29e021996-10-15Fredrik Hübinette (Hubbe)  * This function is called when an object runs out of references. * It frees the object if it is destructed, otherwise it moves it to * a separate list of objects which will be destructed later. */
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void schedule_really_free_object(struct object *o)
a29e021996-10-15Fredrik Hübinette (Hubbe) {
e2d9e62000-06-10Martin Stjernholm #ifdef PIKE_DEBUG
d631b82002-12-01Martin Stjernholm  if (o->refs) { #ifdef DEBUG_MALLOC
6ff38a2004-04-03Martin Stjernholm  if (o->refs > 0) { fprintf (stderr, "Object got %d references in schedule_really_free_object():\n", o->refs); describe_something(o, T_OBJECT, 0,2,0, NULL); }
d631b82002-12-01Martin Stjernholm #endif
6ff38a2004-04-03Martin Stjernholm  Pike_fatal("Object got %d references in schedule_really_free_object().\n", o->refs);
d631b82002-12-01Martin Stjernholm  }
45c1562010-04-10Martin Stjernholm  if (Pike_in_gc > GC_PASS_PREPARE && Pike_in_gc < GC_PASS_FREE && /* Fake objects are invisible to the gc. */ o->next != o) gc_fatal(o, 0, "Freeing objects is not allowed inside the gc.\n");
e2d9e62000-06-10Martin Stjernholm #endif
a4033e2000-04-14Fredrik Hübinette (Hubbe)  debug_malloc_touch(o);
648a1a2000-06-22Fredrik Hübinette (Hubbe)  debug_malloc_touch(o->storage);
e2d9e62000-06-10Martin Stjernholm 
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  if(o->prog && (o->prog->flags & PROGRAM_DESTRUCT_IMMEDIATE))
b504ed1997-09-21Fredrik Hübinette (Hubbe)  {
8c83371998-04-16Fredrik Hübinette (Hubbe)  add_ref(o);
09f2882005-02-09Martin Stjernholm  destruct_object (o, DESTRUCT_NO_REFS);
50ea682003-03-14Henrik Grubbström (Grubba)  if(sub_ref(o)) return;
b504ed1997-09-21Fredrik Hübinette (Hubbe)  }
a4033e2000-04-14Fredrik Hübinette (Hubbe)  debug_malloc_touch(o);
648a1a2000-06-22Fredrik Hübinette (Hubbe)  debug_malloc_touch(o->storage);
a29e021996-10-15Fredrik Hübinette (Hubbe) 
171c6b2005-03-18Henrik Grubbström (Grubba)  if (o->next != o) { /* Don't unlink fake objects... */ DOUBLEUNLINK(first_object,o); }
a29e021996-10-15Fredrik Hübinette (Hubbe)  if(o->prog) {
aec5af2001-01-22Martin Stjernholm  o->next = objects_to_destruct;
7c2e072010-04-11Martin Stjernholm #ifdef PIKE_DEBUG o->prev = (void *) -3; #endif
aff3602002-11-23Martin Stjernholm  PIKE_MEM_WO(o->prev);
aec5af2001-01-22Martin Stjernholm  objects_to_destruct = o;
e2d9e62000-06-10Martin Stjernholm  #ifdef GC_VERBOSE if (Pike_in_gc > GC_PASS_PREPARE) fprintf(stderr, "| Putting %p in objects_to_destruct.\n", o); #endif
7bf6232000-04-23Martin Stjernholm  if (Pike_in_gc > GC_PASS_PREPARE && Pike_in_gc < GC_PASS_DESTRUCT)
e2d9e62000-06-10Martin Stjernholm  /* destruct_objects_to_destruct() called by gc instead. */
7bf6232000-04-23Martin Stjernholm  return;
90867d1997-07-14Fredrik Hübinette (Hubbe)  if(!destruct_object_evaluator_callback)
a29e021996-10-15Fredrik Hübinette (Hubbe)  { destruct_object_evaluator_callback= add_to_callback(&evaluator_callbacks,
2ac9502001-08-14Fredrik Hübinette (Hubbe)  (callback_func)destruct_objects_to_destruct_cb,
a29e021996-10-15Fredrik Hübinette (Hubbe)  0,0); } } else {
f3c7152001-04-14Fredrik Hübinette (Hubbe) #if 0 /* Did I just cause a leak? -Hubbe */ if(o->prog && o->prog->flags & PROGRAM_USES_PARENT)
31e4901999-03-27Henrik Grubbström (Grubba)  {
f3c7152001-04-14Fredrik Hübinette (Hubbe)  if(PARENT_INFO(o)->parent) { /* fprintf(stderr, "schedule_really_free_object(): Zapping parent.\n"); */
31e4901999-03-27Henrik Grubbström (Grubba) 
f3c7152001-04-14Fredrik Hübinette (Hubbe)  free_object(PARENT_INFO(o)->parent); PARENT_INFO(o)->parent=0; }
31e4901999-03-27Henrik Grubbström (Grubba)  }
f3c7152001-04-14Fredrik Hübinette (Hubbe) #endif
31e4901999-03-27Henrik Grubbström (Grubba) 
e2d9e62000-06-10Martin Stjernholm #ifdef GC_VERBOSE if (Pike_in_gc > GC_PASS_PREPARE) fprintf(stderr, "| Freeing storage for %p.\n", o); #endif
337fe62000-09-29Martin Stjernholm  if (o->next != o) /* As far as the gc is concerned, the fake objects doesn't exist. */ GC_FREE(o);
52b2c42000-07-02Martin Stjernholm 
45637c2001-04-07Fredrik Hübinette (Hubbe)  EXIT_PIKE_MEMOBJ(o);
5d35781999-10-24Henrik Grubbström (Grubba) 
648a1a2000-06-22Fredrik Hübinette (Hubbe)  if(o->storage) { free(o->storage); o->storage=0; } really_free_object(o);
a29e021996-10-15Fredrik Hübinette (Hubbe)  }
5267b71995-08-09Fredrik Hübinette (Hubbe) }
77fbd72010-11-25Henrik Grubbström (Grubba) static void assign_svalue_from_ptr_no_free(struct svalue *to, struct object *o, int run_time_type, union idptr func) { void *ptr = PIKE_OBJ_STORAGE(o) + func.offset; switch(run_time_type) { case T_SVALUE_PTR: { struct svalue *s = func.sval; check_destructed(s); assign_svalue_no_free(to, s); break; }
72b0812013-06-11Per Hedbor 
77fbd72010-11-25Henrik Grubbström (Grubba)  case T_OBJ_INDEX: {
017b572011-10-28Henrik Grubbström (Grubba)  SET_SVAL(*to, T_FUNCTION, DO_NOT_WARN(func.offset), object, o);
77fbd72010-11-25Henrik Grubbström (Grubba)  add_ref(o); break; }
8802482010-11-25Henrik Grubbström (Grubba)  case PIKE_T_GET_SET: { int fun = func.gs_info.getter; if (fun >= 0) { DECLARE_CYCLIC(); if (!BEGIN_CYCLIC(o, (size_t) fun)) { SET_CYCLIC_RET(1); apply_low(o, fun, 0); } else { END_CYCLIC(); Pike_error("Cyclic loop on getter.\n"); } END_CYCLIC(); *to = *(--Pike_sp); } else { Pike_error("No getter for variable.\n"); } break; }
72b0812013-06-11Per Hedbor 
77fbd72010-11-25Henrik Grubbström (Grubba)  case T_MIXED:
8181912010-11-25Henrik Grubbström (Grubba)  case PIKE_T_NO_REF_MIXED:
77fbd72010-11-25Henrik Grubbström (Grubba)  { struct svalue *s=(struct svalue *)ptr; check_destructed(s); assign_svalue_no_free(to, s); break; } case T_FLOAT:
8181912010-11-25Henrik Grubbström (Grubba)  case PIKE_T_NO_REF_FLOAT:
017b572011-10-28Henrik Grubbström (Grubba)  SET_SVAL(*to, T_FLOAT, 0, float_number, *(FLOAT_TYPE *)ptr);
77fbd72010-11-25Henrik Grubbström (Grubba)  break; case T_INT:
8181912010-11-25Henrik Grubbström (Grubba)  case PIKE_T_NO_REF_INT:
017b572011-10-28Henrik Grubbström (Grubba)  SET_SVAL(*to, T_INT, NUMBER_NUMBER, integer, *(INT_TYPE *)ptr);
77fbd72010-11-25Henrik Grubbström (Grubba)  break; default: { struct ref_dummy *dummy; if((dummy=*(struct ref_dummy **)ptr)) {
017b572011-10-28Henrik Grubbström (Grubba)  SET_SVAL(*to, run_time_type & ~PIKE_T_NO_REF_FLAG, 0, dummy, dummy); add_ref(dummy);
77fbd72010-11-25Henrik Grubbström (Grubba)  }else{
017b572011-10-28Henrik Grubbström (Grubba)  SET_SVAL(*to, T_INT, NUMBER_NUMBER, integer, 0);
77fbd72010-11-25Henrik Grubbström (Grubba)  } break; } } }
5267b71995-08-09Fredrik Hübinette (Hubbe) 
a903032003-02-16Martin Stjernholm /* Get a variable through internal indexing, i.e. directly by
6b11412003-11-18Henrik Grubbström (Grubba)  * identifier index without going through `->= or `[]= lfuns. * * NOTE: This function may be called by the compiler on objects * cloned from unfinished programs (ie placeholder * objects). Degenerated cases may thus occur.
479afe2010-02-09Henrik Grubbström (Grubba)  * It may also be called via lfuns in the currently * compiling program (notably lfun::`->()) and thus * execute in place-holder objacts.
6b11412003-11-18Henrik Grubbström (Grubba)  */
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void low_object_index_no_free(struct svalue *to,
bdd6302000-08-10Henrik Grubbström (Grubba)  struct object *o, ptrdiff_t f)
4a66491995-11-13Per Hedbor { struct identifier *i;
2560e92007-09-25Henrik Grubbström (Grubba)  struct program *p = NULL;
77fbd72010-11-25Henrik Grubbström (Grubba)  struct reference *ref;
4a66491995-11-13Per Hedbor 
2560e92007-09-25Henrik Grubbström (Grubba)  while(1) { struct external_variable_context loc; if(!o || !(p = o->prog)) { Pike_error("Cannot access variables in destructed object.\n"); } debug_malloc_touch(o); debug_malloc_touch(o->storage);
77fbd72010-11-25Henrik Grubbström (Grubba)  if ((ref = PTR_FROM_INT(p, f))->run_time_type != PIKE_T_UNKNOWN) { /* Cached vtable lookup. * * The most common cases of object indexing should match these. */ assign_svalue_from_ptr_no_free(to, o, ref->run_time_type, ref->func); return; } i=ID_FROM_PTR(p, ref);
2560e92007-09-25Henrik Grubbström (Grubba) 
64dd452007-09-29Henrik Grubbström (Grubba)  if (!IDENTIFIER_IS_ALIAS(i->identifier_flags)) break;
e1fed61999-09-09Fredrik Hübinette (Hubbe) 
2560e92007-09-25Henrik Grubbström (Grubba)  loc.o = o; loc.inherit = INHERIT_FROM_INT(p, f); loc.parent_identifier = f; find_external_context(&loc, i->func.ext_ref.depth); f = i->func.ext_ref.id + loc.inherit->identifier_level; o = loc.o; }
4a66491995-11-13Per Hedbor 
28553d2003-08-03Martin Stjernholm  switch(i->identifier_flags & IDENTIFIER_TYPE_MASK)
4a66491995-11-13Per Hedbor  {
a192d81999-12-15Martin Stjernholm  case IDENTIFIER_PIKE_FUNCTION:
c914bd2003-03-09Henrik Grubbström (Grubba)  if (i->func.offset == -1 && p->flags & PROGRAM_FINISHED) {
2b9b222003-02-24Martin Stjernholm  /* Prototype. In the first pass we must be able to get a
c914bd2003-03-09Henrik Grubbström (Grubba)  * function anyway. * * We also need to get a function anyway if we're currently * in the second pass of compiling this program, since the * function might be defined further ahead.
354bbe2007-09-24Henrik Grubbström (Grubba)  * * FIXME: Consider looking at IDENTIFIER_HAS_BODY in pass 2? * * On the other hand, consider mixins.
c914bd2003-03-09Henrik Grubbström (Grubba)  */
017b572011-10-28Henrik Grubbström (Grubba)  SET_SVAL(*to, T_INT, NUMBER_UNDEFINED, integer, 0);
a192d81999-12-15Martin Stjernholm  break; }
28553d2003-08-03Martin Stjernholm  /* Fall through. */
d2c6081996-11-07Fredrik Hübinette (Hubbe)  case IDENTIFIER_C_FUNCTION:
77fbd72010-11-25Henrik Grubbström (Grubba)  ref->func.offset = f; ref->run_time_type = T_OBJ_INDEX;
017b572011-10-28Henrik Grubbström (Grubba)  SET_SVAL(*to, T_FUNCTION, DO_NOT_WARN(f), object, o);
8c83371998-04-16Fredrik Hübinette (Hubbe)  add_ref(o);
d2c6081996-11-07Fredrik Hübinette (Hubbe)  break; case IDENTIFIER_CONSTANT: {
89378b2010-11-23Henrik Grubbström (Grubba)  if (i->func.const_info.offset >= 0) {
d12fe42003-08-20Henrik Grubbström (Grubba)  struct svalue *s;
89378b2010-11-23Henrik Grubbström (Grubba)  s=& PROG_FROM_INT(p,f)->constants[i->func.const_info.offset].sval;
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(*s) == T_PROGRAM &&
d12fe42003-08-20Henrik Grubbström (Grubba)  (s->u.program->flags & PROGRAM_USES_PARENT)) {
017b572011-10-28Henrik Grubbström (Grubba)  SET_SVAL(*to, T_FUNCTION, DO_NOT_WARN(f), object, o);
d12fe42003-08-20Henrik Grubbström (Grubba)  add_ref(o); }else{
77fbd72010-11-25Henrik Grubbström (Grubba)  if (p->flags & PROGRAM_OPTIMIZED) { ref->func.sval = s; ref->run_time_type = T_SVALUE_PTR; }
d12fe42003-08-20Henrik Grubbström (Grubba)  check_destructed(s); assign_svalue_no_free(to, s); } } else { /* Prototype constant. */
017b572011-10-28Henrik Grubbström (Grubba)  SET_SVAL(*to, T_INT, NUMBER_NUMBER, integer, 0);
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  }
d2c6081996-11-07Fredrik Hübinette (Hubbe)  break; }
28553d2003-08-03Martin Stjernholm  case IDENTIFIER_VARIABLE:
417e952006-10-27Henrik Grubbström (Grubba)  if (i->run_time_type == PIKE_T_GET_SET) {
85e4552008-05-13Henrik Grubbström (Grubba)  int fun = i->func.gs_info.getter;
417e952006-10-27Henrik Grubbström (Grubba)  if (fun >= 0) {
24baa72006-10-28Henrik Grubbström (Grubba)  fun += p->inherits[ref->inherit_offset].identifier_level;
417e952006-10-27Henrik Grubbström (Grubba)  }
8802482010-11-25Henrik Grubbström (Grubba)  ref->func.gs_info.getter = fun; fun = i->func.gs_info.setter; if (fun >= 0) { fun += p->inherits[ref->inherit_offset].identifier_level; } ref->func.gs_info.setter = fun; ref->run_time_type = PIKE_T_GET_SET; assign_svalue_from_ptr_no_free(to, o, ref->run_time_type, ref->func);
479afe2010-02-09Henrik Grubbström (Grubba)  } else if (!(p->flags & PROGRAM_FINISHED) || (i->run_time_type == PIKE_T_FREE) || !PIKE_OBJ_STORAGE(o)) {
d842af2006-01-12Henrik Grubbström (Grubba)  /* Variable storage not allocated. */ #ifdef PIKE_DEBUG
1d46fd2008-05-29Henrik Grubbström (Grubba)  if ((i->run_time_type != PIKE_T_FREE) && (p->flags & PROGRAM_FINISHED)) {
d842af2006-01-12Henrik Grubbström (Grubba)  Pike_fatal("Object without variable storage!\n");
0f7a562001-09-06Fredrik Hübinette (Hubbe)  }
d842af2006-01-12Henrik Grubbström (Grubba) #endif /* PIKE_DEBUG */
017b572011-10-28Henrik Grubbström (Grubba)  SET_SVAL(*to, T_INT, ((i->run_time_type == PIKE_T_FREE)? NUMBER_UNDEFINED:NUMBER_NUMBER), integer, 0);
d842af2006-01-12Henrik Grubbström (Grubba)  } else {
77fbd72010-11-25Henrik Grubbström (Grubba)  ref->func.offset = INHERIT_FROM_INT(o->prog, f)->storage_offset + i->func.offset; ref->run_time_type = i->run_time_type;
8181912010-11-25Henrik Grubbström (Grubba)  if (i->identifier_flags & IDENTIFIER_NO_THIS_REF) { ref->run_time_type |= PIKE_T_NO_REF_FLAG; }
77fbd72010-11-25Henrik Grubbström (Grubba)  assign_svalue_from_ptr_no_free(to, o, ref->run_time_type, ref->func);
d2c6081996-11-07Fredrik Hübinette (Hubbe)  }
28553d2003-08-03Martin Stjernholm  break;
46c35d2003-08-03Martin Stjernholm  default:;
28553d2003-08-03Martin Stjernholm #ifdef PIKE_DEBUG Pike_fatal ("Unknown identifier type.\n"); #endif
0f7a562001-09-06Fredrik Hübinette (Hubbe)  }
4a66491995-11-13Per Hedbor }
a903032003-02-16Martin Stjernholm /* Get a variable without going through `->= or `[]= lfuns. If index * is a string then the externally visible identifiers are indexed. If * index is T_OBJ_INDEX then any identifier is accessed through * identifier index. */
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void object_index_no_free2(struct svalue *to,
a903032003-02-16Martin Stjernholm  struct object *o,
9273742008-05-29Henrik Grubbström (Grubba)  int inherit_number,
a903032003-02-16Martin Stjernholm  struct svalue *index)
5267b71995-08-09Fredrik Hübinette (Hubbe) { struct program *p;
9273742008-05-29Henrik Grubbström (Grubba)  struct inherit *inh;
37b8782000-11-02Henrik Grubbström (Grubba)  int f = -1;
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(!o || !(p=o->prog))
2a50961995-08-23Fredrik Hübinette (Hubbe)  {
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Lookup in destructed object.\n");
2a50961995-08-23Fredrik Hübinette (Hubbe)  return; /* make gcc happy */ }
5267b71995-08-09Fredrik Hübinette (Hubbe) 
9273742008-05-29Henrik Grubbström (Grubba)  p = (inh = p->inherits + inherit_number)->prog;
017b572011-10-28Henrik Grubbström (Grubba)  switch(TYPEOF(*index))
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  { case T_STRING: f=find_shared_string_identifier(index->u.string, p);
9273742008-05-29Henrik Grubbström (Grubba)  if (f >= 0) f += inh->identifier_level;
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  break;
cd83521998-02-02Fredrik Hübinette (Hubbe) 
a903032003-02-16Martin Stjernholm  case T_OBJ_INDEX: f=index->u.identifier;
8ff47f1998-02-03Fredrik Hübinette (Hubbe)  break;
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  default:
a903032003-02-16Martin Stjernholm #ifdef PIKE_DEBUG
017b572011-10-28Henrik Grubbström (Grubba)  if (TYPEOF(*index) > MAX_TYPE) Pike_fatal ("Invalid type %d in index.\n", TYPEOF(*index));
a903032003-02-16Martin Stjernholm #endif
2f40942002-04-03Martin Stjernholm  Pike_error("Lookup in object with non-string index.\n");
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  }
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(f < 0) {
017b572011-10-28Henrik Grubbström (Grubba)  SET_SVAL(*to, T_INT, NUMBER_UNDEFINED, integer, 0);
5267b71995-08-09Fredrik Hübinette (Hubbe)  }else{
cde51b1996-08-03Fredrik Hübinette (Hubbe)  low_object_index_no_free(to, o, f);
5267b71995-08-09Fredrik Hübinette (Hubbe)  } }
017b572011-10-28Henrik Grubbström (Grubba) #define ARROW_INDEX_P(X) (TYPEOF(*(X)) == T_STRING && SUBTYPEOF(*(X)))
cde51b1996-08-03Fredrik Hübinette (Hubbe) 
a903032003-02-16Martin Stjernholm /* Get a variable through external indexing, i.e. by going through
9779872008-06-28Martin Stjernholm  * `-> or `[] lfuns, not seeing private and protected etc. */
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void object_index_no_free(struct svalue *to,
e6a2ed2003-02-15Henrik Grubbström (Grubba)  struct object *o,
9273742008-05-29Henrik Grubbström (Grubba)  int inherit_number,
e6a2ed2003-02-15Henrik Grubbström (Grubba)  struct svalue *index)
cde51b1996-08-03Fredrik Hübinette (Hubbe) {
cb787a2000-08-24Henrik Grubbström (Grubba)  struct program *p = NULL;
9273742008-05-29Henrik Grubbström (Grubba)  struct inherit *inh;
eaa4da2001-10-04Fredrik Hübinette (Hubbe)  int lfun,l;
cde51b1996-08-03Fredrik Hübinette (Hubbe)  if(!o || !(p=o->prog)) {
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Lookup in destructed object.\n");
cde51b1996-08-03Fredrik Hübinette (Hubbe)  return; /* make gcc happy */ }
9273742008-05-29Henrik Grubbström (Grubba)  p = (inh = p->inherits + inherit_number)->prog;
a903032003-02-16Martin Stjernholm #ifdef PIKE_DEBUG
017b572011-10-28Henrik Grubbström (Grubba)  if (TYPEOF(*index) > MAX_TYPE) Pike_fatal ("Invalid index type %d.\n", TYPEOF(*index));
a903032003-02-16Martin Stjernholm #endif lfun=ARROW_INDEX_P(index) ? LFUN_ARROW : LFUN_INDEX; if(p->flags & PROGRAM_FIXED) { l=p->lfuns[lfun]; }else{ if(!(p->flags & PROGRAM_PASS_1_DONE))
eaa4da2001-10-04Fredrik Hübinette (Hubbe)  {
a903032003-02-16Martin Stjernholm  if(report_compiler_dependency(p))
eaa4da2001-10-04Fredrik Hübinette (Hubbe)  {
3601d32002-11-23Martin Stjernholm #if 0
dc79222003-03-27Martin Stjernholm  struct svalue tmp; fprintf(stderr,"Placeholder deployed for %p when indexing ", p);
017b572011-10-28Henrik Grubbström (Grubba)  SET_SVAL(tmp, T_OBJECT, 0, object, o);
dc79222003-03-27Martin Stjernholm  print_svalue (stderr, &tmp); fputs (" with ", stderr); print_svalue (stderr, index); fputc ('\n', stderr);
3601d32002-11-23Martin Stjernholm #endif
017b572011-10-28Henrik Grubbström (Grubba)  SET_SVAL(*to, T_OBJECT, 0, object, placeholder_object); add_ref(placeholder_object);
a903032003-02-16Martin Stjernholm  return;
eaa4da2001-10-04Fredrik Hübinette (Hubbe)  } }
a903032003-02-16Martin Stjernholm  l=low_find_lfun(p, lfun); } if(l != -1) {
9273742008-05-29Henrik Grubbström (Grubba)  l += inh->identifier_level;
a903032003-02-16Martin Stjernholm  push_svalue(index); apply_lfun(o, lfun, 1); *to=sp[-1]; sp--; dmalloc_touch_svalue(sp);
cde51b1996-08-03Fredrik Hübinette (Hubbe)  } else {
9273742008-05-29Henrik Grubbström (Grubba)  object_index_no_free2(to, o, inherit_number, index);
5267b71995-08-09Fredrik Hübinette (Hubbe)  } }
8181912010-11-25Henrik Grubbström (Grubba) static void object_lower_set_index(struct object *o, union idptr func, int rtt, struct svalue *from) { do { void *ptr = PIKE_OBJ_STORAGE(o) + func.offset; union anything *u = (union anything *)ptr; struct svalue *to = (struct svalue *)ptr; switch(rtt) { case T_SVALUE_PTR: case T_OBJ_INDEX: Pike_error("Cannot assign functions or constants.\n"); continue; case PIKE_T_FREE: Pike_error("Attempt to store data in extern variable.\n"); continue;
8802482010-11-25Henrik Grubbström (Grubba)  case PIKE_T_GET_SET: { int fun = func.gs_info.setter; if (fun >= 0) { DECLARE_CYCLIC(); if (!BEGIN_CYCLIC(o, (size_t) fun)) { SET_CYCLIC_RET(1); push_svalue(from); apply_low(o, fun, 1); pop_stack(); } else { END_CYCLIC(); Pike_error("Cyclic loop on setter.\n"); } END_CYCLIC(); } else { Pike_error("No setter for variable.\n"); } continue; }
8181912010-11-25Henrik Grubbström (Grubba)  /* Partial code duplication from assign_to_short_svalue. */ case T_MIXED: /* Count references to ourselves. */ assign_svalue(to, from); continue; case PIKE_T_NO_REF_MIXED: /* Don't count references to ourselves to help the gc. DDTAH. */ dmalloc_touch_svalue(to);
017b572011-10-28Henrik Grubbström (Grubba)  if ((TYPEOF(*to) != T_OBJECT && TYPEOF(*to) != T_FUNCTION) ||
8181912010-11-25Henrik Grubbström (Grubba)  to->u.object != o) { (void) debug_malloc_update_location(o, DMALLOC_NAMED_LOCATION(" free_global")); free_svalue(to); #ifdef DEBUG_MALLOC } else { (void) debug_malloc_update_location(o, DMALLOC_NAMED_LOCATION(" skip_global")); dmalloc_touch_svalue (to); #endif /* DEBUG_MALLOC */ } *to = *from; dmalloc_touch_svalue (to);
017b572011-10-28Henrik Grubbström (Grubba)  if ((TYPEOF(*to) != T_OBJECT && TYPEOF(*to) != T_FUNCTION) ||
8181912010-11-25Henrik Grubbström (Grubba)  (to->u.object != o)) {
4a93e82013-06-11Henrik Grubbström (Grubba)  if(REFCOUNTED_TYPE(TYPEOF(*to))) {
8181912010-11-25Henrik Grubbström (Grubba)  (void) debug_malloc_update_location(o, DMALLOC_NAMED_LOCATION(" store_global")); add_ref(to->u.dummy); #ifdef DEBUG_MALLOC } else { (void) debug_malloc_update_location(o, DMALLOC_NAMED_LOCATION(" store_global")); #endif /* DEBUG_MALLOC */ } #ifdef DEBUG_MALLOC } else { (void) debug_malloc_update_location(o, DMALLOC_NAMED_LOCATION(" self_global")); dmalloc_touch_svalue (to); #endif /* DEBUG_MALLOC */ } continue; case T_INT: case PIKE_T_NO_REF_INT:
017b572011-10-28Henrik Grubbström (Grubba)  if (TYPEOF(*from) != T_INT) break;
8181912010-11-25Henrik Grubbström (Grubba)  u->integer=from->u.integer; continue; case T_FLOAT: case PIKE_T_NO_REF_FLOAT:
017b572011-10-28Henrik Grubbström (Grubba)  if (TYPEOF(*from) != T_FLOAT) break;
8181912010-11-25Henrik Grubbström (Grubba)  u->float_number=from->u.float_number; continue; case PIKE_T_NO_REF_OBJECT:
0947c92013-06-12Per Hedbor  { int is_zero = UNSAFE_IS_ZERO(from); /* Don't count references to ourselves to help the gc. */ if ((TYPEOF(*from) != T_OBJECT) && !is_zero) break; debug_malloc_touch(u->object); if ((u->object != o) && u->refs && !sub_ref(u->dummy)) { debug_malloc_touch(o); really_free_short_svalue(u,rtt);
8181912010-11-25Henrik Grubbström (Grubba) #ifdef DEBUG_MALLOC
0947c92013-06-12Per Hedbor  } else { debug_malloc_touch(o);
8181912010-11-25Henrik Grubbström (Grubba) #endif /* DEBUG_MALLOC */
0947c92013-06-12Per Hedbor  } if (is_zero) { debug_malloc_touch(u->ptr); u->refs = NULL; continue; }
8181912010-11-25Henrik Grubbström (Grubba)  } u->refs = from->u.refs; debug_malloc_touch(u->refs); if (u->object != o) { debug_malloc_touch(o); add_ref(u->dummy); #ifdef DEBUG_MALLOC } else { debug_malloc_touch(o); #endif /* DEBUG_MALLOC */ } continue; default:
0947c92013-06-12Per Hedbor  { int is_zero = UNSAFE_IS_ZERO(from); rtt &= ~PIKE_T_NO_REF_FLAG; if ((rtt != TYPEOF(*from)) && !is_zero) break; /* Error. */ debug_malloc_touch(u->refs); if(u->refs && !sub_ref(u->dummy)) really_free_short_svalue(u, rtt); if (is_zero) { debug_malloc_touch(u->ptr); u->refs = NULL; continue; } u->refs = from->u.refs; add_ref(u->dummy); continue;
8181912010-11-25Henrik Grubbström (Grubba)  } } Pike_error("Wrong type in assignment, expected %s, got %s.\n", get_name_of_type(rtt & ~PIKE_T_NO_REF_FLAG),
017b572011-10-28Henrik Grubbström (Grubba)  get_name_of_type(TYPEOF(*from)));
8181912010-11-25Henrik Grubbström (Grubba)  } while(0); }
cde51b1996-08-03Fredrik Hübinette (Hubbe) 
a903032003-02-16Martin Stjernholm /* Assign a variable through internal indexing, i.e. directly by * identifier index without going through `->= or `[]= lfuns. */
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void object_low_set_index(struct object *o,
ad28d82003-02-15Henrik Grubbström (Grubba)  int f, struct svalue *from)
5267b71995-08-09Fredrik Hübinette (Hubbe) { struct identifier *i;
cb787a2000-08-24Henrik Grubbström (Grubba)  struct program *p = NULL;
8181912010-11-25Henrik Grubbström (Grubba)  struct reference *ref;
e0d6f52003-02-13Martin Stjernholm  int rtt, id_flags;
5267b71995-08-09Fredrik Hübinette (Hubbe) 
2560e92007-09-25Henrik Grubbström (Grubba)  while(1) { struct external_variable_context loc; if(!o || !(p=o->prog)) { Pike_error("Lookup in destructed object.\n"); return; /* make gcc happy */ } debug_malloc_touch(o); debug_malloc_touch(o->storage);
8181912010-11-25Henrik Grubbström (Grubba)  if ((ref = PTR_FROM_INT(p, f))->run_time_type != PIKE_T_UNKNOWN) { /* Cached vtable lookup. * * The most common cases of object indexing should match these. */ object_lower_set_index(o, ref->func, ref->run_time_type, from); return; }
2560e92007-09-25Henrik Grubbström (Grubba)  i=ID_FROM_INT(p, f);
64dd452007-09-29Henrik Grubbström (Grubba)  if (!IDENTIFIER_IS_ALIAS(i->identifier_flags)) break;
2560e92007-09-25Henrik Grubbström (Grubba)  loc.o = o; loc.inherit = INHERIT_FROM_INT(p, f); loc.parent_identifier = f; find_external_context(&loc, i->func.ext_ref.depth); f = i->func.ext_ref.id + loc.inherit->identifier_level; o = loc.o;
2a50961995-08-23Fredrik Hübinette (Hubbe)  }
5267b71995-08-09Fredrik Hübinette (Hubbe)  check_destructed(from);
e0d6f52003-02-13Martin Stjernholm  rtt = i->run_time_type; id_flags = i->identifier_flags;
5267b71995-08-09Fredrik Hübinette (Hubbe) 
e0d6f52003-02-13Martin Stjernholm  if(!IDENTIFIER_IS_VARIABLE(id_flags))
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Cannot assign functions or constants.\n");
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
e0d6f52003-02-13Martin Stjernholm  else if(rtt == T_MIXED)
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
8181912010-11-25Henrik Grubbström (Grubba)  ref->func.offset = INHERIT_FROM_INT(p, f)->storage_offset + i->func.offset; ref->run_time_type = i->run_time_type; if (id_flags & IDENTIFIER_NO_THIS_REF) { ref->run_time_type |= PIKE_T_NO_REF_FLAG;
50ea682003-03-14Henrik Grubbström (Grubba)  }
8181912010-11-25Henrik Grubbström (Grubba)  object_lower_set_index(o, ref->func, ref->run_time_type, from);
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
417e952006-10-27Henrik Grubbström (Grubba)  else if (rtt == PIKE_T_GET_SET) { /* Getter/setter type variable. */ struct reference *ref = p->identifier_references + f; struct program *pp = p->inherits[ref->inherit_offset].prog;
8802482010-11-25Henrik Grubbström (Grubba)  int fun = i->func.gs_info.getter; if (fun >= 0) { fun += p->inherits[ref->inherit_offset].identifier_level; } ref->func.gs_info.getter = fun; fun = i->func.gs_info.setter;
417e952006-10-27Henrik Grubbström (Grubba)  if (fun >= 0) {
24baa72006-10-28Henrik Grubbström (Grubba)  fun += p->inherits[ref->inherit_offset].identifier_level;
417e952006-10-27Henrik Grubbström (Grubba)  }
8802482010-11-25Henrik Grubbström (Grubba)  ref->func.gs_info.setter = fun; ref->run_time_type = PIKE_T_GET_SET; object_lower_set_index(o, ref->func, ref->run_time_type, from);
417e952006-10-27Henrik Grubbström (Grubba)  }
2e1a6a2008-05-29Henrik Grubbström (Grubba)  else if (rtt == PIKE_T_FREE) { Pike_error("Attempt to store data in extern variable %S.\n", i->name); } else {
8181912010-11-25Henrik Grubbström (Grubba)  ref->func.offset = INHERIT_FROM_INT(p, f)->storage_offset + i->func.offset; ref->run_time_type = i->run_time_type; if (id_flags & IDENTIFIER_NO_THIS_REF) { ref->run_time_type |= PIKE_T_NO_REF_FLAG;
8d4faf2003-02-10Martin Stjernholm  }
8181912010-11-25Henrik Grubbström (Grubba)  object_lower_set_index(o, ref->func, ref->run_time_type, from);
5267b71995-08-09Fredrik Hübinette (Hubbe)  } }
a903032003-02-16Martin Stjernholm /* Assign a variable without going through `->= or `[]= lfuns. If * index is a string then the externally visible identifiers are * indexed. If index is T_OBJ_INDEX then any identifier is accessed * through identifier index. */
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void object_set_index2(struct object *o,
9273742008-05-29Henrik Grubbström (Grubba)  int inherit_number,
ad28d82003-02-15Henrik Grubbström (Grubba)  struct svalue *index, struct svalue *from)
5267b71995-08-09Fredrik Hübinette (Hubbe) { struct program *p;
9273742008-05-29Henrik Grubbström (Grubba)  struct inherit *inh;
37b8782000-11-02Henrik Grubbström (Grubba)  int f = -1;
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(!o || !(p=o->prog))
2a50961995-08-23Fredrik Hübinette (Hubbe)  {
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Lookup in destructed object.\n");
2a50961995-08-23Fredrik Hübinette (Hubbe)  return; /* make gcc happy */ }
5267b71995-08-09Fredrik Hübinette (Hubbe) 
9273742008-05-29Henrik Grubbström (Grubba)  p = (inh = p->inherits + inherit_number)->prog;
017b572011-10-28Henrik Grubbström (Grubba)  switch(TYPEOF(*index))
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  { case T_STRING: f=find_shared_string_identifier(index->u.string, p);
9273742008-05-29Henrik Grubbström (Grubba)  if (f >= 0) f += inh->identifier_level;
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  break;
a903032003-02-16Martin Stjernholm  case T_OBJ_INDEX: f=index->u.identifier;
8ff47f1998-02-03Fredrik Hübinette (Hubbe)  break;
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  default:
a903032003-02-16Martin Stjernholm #ifdef PIKE_DEBUG
017b572011-10-28Henrik Grubbström (Grubba)  if (TYPEOF(*index) > MAX_TYPE) Pike_fatal ("Invalid type %d in index.\n", TYPEOF(*index));
a903032003-02-16Martin Stjernholm #endif
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Lookup on non-string value.\n");
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  }
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(f < 0) {
017b572011-10-28Henrik Grubbström (Grubba)  if (TYPEOF(*index) == T_STRING && index->u.string->len < 1024)
9606eb2004-11-12Henrik Grubbström (Grubba)  Pike_error("No such variable (%S) in object.\n", index->u.string);
a903032003-02-16Martin Stjernholm  else
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("No such variable in object.\n");
5267b71995-08-09Fredrik Hübinette (Hubbe)  }else{ object_low_set_index(o, f, from); } }
a903032003-02-16Martin Stjernholm /* Assign a variable through external indexing, i.e. by going through
9779872008-06-28Martin Stjernholm  * `->= or `[]= lfuns, not seeing private and protected etc. */
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void object_set_index(struct object *o,
9273742008-05-29Henrik Grubbström (Grubba)  int inherit_number,
ad28d82003-02-15Henrik Grubbström (Grubba)  struct svalue *index, struct svalue *from)
cde51b1996-08-03Fredrik Hübinette (Hubbe) {
a903032003-02-16Martin Stjernholm  int lfun;
9273742008-05-29Henrik Grubbström (Grubba)  int fun;
cb787a2000-08-24Henrik Grubbström (Grubba)  struct program *p = NULL;
9273742008-05-29Henrik Grubbström (Grubba)  struct inherit *inh;
5267b71995-08-09Fredrik Hübinette (Hubbe) 
cde51b1996-08-03Fredrik Hübinette (Hubbe)  if(!o || !(p=o->prog)) {
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Lookup in destructed object.\n");
cde51b1996-08-03Fredrik Hübinette (Hubbe)  return; /* make gcc happy */ }
9273742008-05-29Henrik Grubbström (Grubba)  p = (inh = p->inherits + inherit_number)->prog;
a903032003-02-16Martin Stjernholm #ifdef PIKE_DEBUG
017b572011-10-28Henrik Grubbström (Grubba)  if (TYPEOF(*index) > MAX_TYPE) Pike_fatal ("Invalid index type %d.\n", TYPEOF(*index));
a903032003-02-16Martin Stjernholm #endif
dffa011997-01-15Fredrik Hübinette (Hubbe) 
a903032003-02-16Martin Stjernholm  lfun=ARROW_INDEX_P(index) ? LFUN_ASSIGN_ARROW : LFUN_ASSIGN_INDEX;
9273742008-05-29Henrik Grubbström (Grubba)  if((fun = FIND_LFUN(p, lfun)) != -1)
a903032003-02-16Martin Stjernholm  { push_svalue(index); push_svalue(from);
9273742008-05-29Henrik Grubbström (Grubba)  apply_low(o, fun + inh->identifier_level, 2);
a903032003-02-16Martin Stjernholm  pop_stack();
cde51b1996-08-03Fredrik Hübinette (Hubbe)  } else {
9273742008-05-29Henrik Grubbström (Grubba)  object_set_index2(o, inherit_number, index, from);
cde51b1996-08-03Fredrik Hübinette (Hubbe)  } }
5267b71995-08-09Fredrik Hübinette (Hubbe) 
cde51b1996-08-03Fredrik Hübinette (Hubbe) static union anything *object_low_get_item_ptr(struct object *o, int f, TYPE_T type)
5267b71995-08-09Fredrik Hübinette (Hubbe) { struct identifier *i; struct program *p;
50ea682003-03-14Henrik Grubbström (Grubba)  debug_malloc_touch(o);
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(!o || !(p=o->prog))
2a50961995-08-23Fredrik Hübinette (Hubbe)  {
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Lookup in destructed object.\n");
2a50961995-08-23Fredrik Hübinette (Hubbe)  return 0; /* make gcc happy */ }
5267b71995-08-09Fredrik Hübinette (Hubbe) 
50ea682003-03-14Henrik Grubbström (Grubba)  debug_malloc_touch(p);
5267b71995-08-09Fredrik Hübinette (Hubbe)  i=ID_FROM_INT(p, f);
8d4faf2003-02-10Martin Stjernholm #ifdef PIKE_DEBUG
a903032003-02-16Martin Stjernholm  if (type > MAX_TYPE) Pike_fatal ("Invalid type %d.\n", type); if (type == T_OBJECT || type == T_FUNCTION)
8d4faf2003-02-10Martin Stjernholm  Pike_fatal ("Dangerous with the refcount-less this-pointers.\n"); #endif
1145882007-10-05Henrik Grubbström (Grubba)  while (IDENTIFIER_IS_ALIAS(i->identifier_flags)) { struct external_variable_context loc; loc.o = o; loc.inherit = INHERIT_FROM_INT(p, f); loc.parent_identifier = 0; find_external_context(&loc, i->func.ext_ref.depth); f = i->func.ext_ref.id; p = (o = loc.o)->prog; i = ID_FROM_INT(p, f); }
7fda7a1997-09-08Fredrik Hübinette (Hubbe)  if(!IDENTIFIER_IS_VARIABLE(i->identifier_flags))
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Cannot assign functions or constants.\n");
1145882007-10-05Henrik Grubbström (Grubba)  } else if(i->run_time_type == T_MIXED)
5267b71995-08-09Fredrik Hübinette (Hubbe)  { struct svalue *s;
a22fdc1996-02-19Fredrik Hübinette (Hubbe)  s=(struct svalue *)LOW_GET_GLOBAL(o,f,i);
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(*s) == type) return & s->u;
5267b71995-08-09Fredrik Hübinette (Hubbe)  } else if(i->run_time_type == type) {
a22fdc1996-02-19Fredrik Hübinette (Hubbe)  return (union anything *) LOW_GET_GLOBAL(o,f,i);
5267b71995-08-09Fredrik Hübinette (Hubbe)  } return 0; } union anything *object_get_item_ptr(struct object *o,
9273742008-05-29Henrik Grubbström (Grubba)  int inherit_number,
5267b71995-08-09Fredrik Hübinette (Hubbe)  struct svalue *index, TYPE_T type) { struct program *p;
9273742008-05-29Henrik Grubbström (Grubba)  struct inherit *inh;
5267b71995-08-09Fredrik Hübinette (Hubbe)  int f;
50ea682003-03-14Henrik Grubbström (Grubba)  debug_malloc_touch(o); dmalloc_touch_svalue(index);
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(!o || !(p=o->prog))
2a50961995-08-23Fredrik Hübinette (Hubbe)  {
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Lookup in destructed object.\n");
2a50961995-08-23Fredrik Hübinette (Hubbe)  return 0; /* make gcc happy */ }
5267b71995-08-09Fredrik Hübinette (Hubbe) 
9273742008-05-29Henrik Grubbström (Grubba)  p = (inh = p->inherits + inherit_number)->prog;
dffa011997-01-15Fredrik Hübinette (Hubbe) 
017b572011-10-28Henrik Grubbström (Grubba)  switch(TYPEOF(*index))
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  { case T_STRING:
542b131999-07-16Fredrik Hübinette (Hubbe)  f=ARROW_INDEX_P(index) ? LFUN_ASSIGN_ARROW : LFUN_ASSIGN_INDEX; if(FIND_LFUN(p,f) != -1) { return 0;
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  /* Pike_error("Cannot do incremental operations on overloaded index (yet).\n");
542b131999-07-16Fredrik Hübinette (Hubbe)  */ }
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  f=find_shared_string_identifier(index->u.string, p);
9273742008-05-29Henrik Grubbström (Grubba)  if (f >= 0) f += inh->identifier_level;
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  break;
a903032003-02-16Martin Stjernholm  case T_OBJ_INDEX: f=index->u.identifier;
8ff47f1998-02-03Fredrik Hübinette (Hubbe)  break;
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  default:
a903032003-02-16Martin Stjernholm #ifdef PIKE_DEBUG
017b572011-10-28Henrik Grubbström (Grubba)  if (TYPEOF(*index) > MAX_TYPE) Pike_fatal ("Invalid type %d in index.\n", TYPEOF(*index));
a903032003-02-16Martin Stjernholm #endif
b2d3e42000-12-01Fredrik Hübinette (Hubbe) /* Pike_error("Lookup on non-string value.\n"); */
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  return 0; }
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(f < 0) {
017b572011-10-28Henrik Grubbström (Grubba)  if (TYPEOF(*index) == T_STRING && index->u.string->len < 1024)
9606eb2004-11-12Henrik Grubbström (Grubba)  Pike_error("No such variable (%S) in object.\n", index->u.string);
a903032003-02-16Martin Stjernholm  else Pike_error("No such variable in object.\n");
5267b71995-08-09Fredrik Hübinette (Hubbe)  }else{ return object_low_get_item_ptr(o, f, type); } return 0; }
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT int object_equal_p(struct object *a, struct object *b, struct processing *p)
5267b71995-08-09Fredrik Hübinette (Hubbe) { struct processing curr; if(a == b) return 1; if(a->prog != b->prog) return 0; curr.pointer_a = a; curr.pointer_b = b; curr.next = p; for( ;p ;p=p->next) if(p->pointer_a == (void *)a && p->pointer_b == (void *)b) return 1;
5d35781999-10-24Henrik Grubbström (Grubba)  /* NOTE: At this point a->prog and b->prog are equal (see test 2 above). */ if(a->prog)
5267b71995-08-09Fredrik Hübinette (Hubbe)  { int e;
2ba9191999-10-23Fredrik Hübinette (Hubbe)  if(a->prog->flags & PROGRAM_HAS_C_METHODS) return 0;
3568101997-10-16Fredrik Hübinette (Hubbe)  for(e=0;e<(int)a->prog->num_identifier_references;e++)
5267b71995-08-09Fredrik Hübinette (Hubbe)  { struct identifier *i; i=ID_FROM_INT(a->prog, e);
2ba9191999-10-23Fredrik Hübinette (Hubbe) 
64dd452007-09-29Henrik Grubbström (Grubba)  if(!IDENTIFIER_IS_VARIABLE(i->identifier_flags) || IDENTIFIER_IS_ALIAS(i->identifier_flags))
5267b71995-08-09Fredrik Hübinette (Hubbe)  continue; if(i->run_time_type == T_MIXED) {
a22fdc1996-02-19Fredrik Hübinette (Hubbe)  if(!low_is_equal((struct svalue *)LOW_GET_GLOBAL(a,e,i), (struct svalue *)LOW_GET_GLOBAL(b,e,i), &curr))
5267b71995-08-09Fredrik Hübinette (Hubbe)  return 0; }else{
a22fdc1996-02-19Fredrik Hübinette (Hubbe)  if(!low_short_is_equal((union anything *)LOW_GET_GLOBAL(a,e,i), (union anything *)LOW_GET_GLOBAL(b,e,i),
5267b71995-08-09Fredrik Hübinette (Hubbe)  i->run_time_type, &curr)) return 0; } } }
94e3581999-10-26Henrik Grubbström (Grubba)  return 1;
5267b71995-08-09Fredrik Hübinette (Hubbe) }
9273742008-05-29Henrik Grubbström (Grubba) PMOD_EXPORT struct array *object_indices(struct object *o, int inherit_number)
4a66491995-11-13Per Hedbor { struct program *p;
9273742008-05-29Henrik Grubbström (Grubba)  struct inherit *inh;
4a66491995-11-13Per Hedbor  struct array *a;
9273742008-05-29Henrik Grubbström (Grubba)  int fun;
4a66491995-11-13Per Hedbor  int e; p=o->prog; if(!p)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("indices() on destructed object.\n");
4a66491995-11-13Per Hedbor 
9273742008-05-29Henrik Grubbström (Grubba)  p = (inh = p->inherits + inherit_number)->prog; if((fun = FIND_LFUN(p, LFUN__INDICES)) == -1)
4a66491995-11-13Per Hedbor  {
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  a=allocate_array_no_init(p->num_identifier_index,0); for(e=0;e<(int)p->num_identifier_index;e++)
a0f9071997-01-26Fredrik Hübinette (Hubbe)  {
017b572011-10-28Henrik Grubbström (Grubba)  SET_SVAL(ITEM(a)[e], T_STRING, 0, string, ID_FROM_INT(p,p->identifier_index[e])->name); add_ref(ITEM(a)[e].u.string);
a0f9071997-01-26Fredrik Hübinette (Hubbe)  }
2523ce2003-04-28Martin Stjernholm  a->type_field = BIT_STRING;
a0f9071997-01-26Fredrik Hübinette (Hubbe)  }else{
9273742008-05-29Henrik Grubbström (Grubba)  apply_low(o, fun + inh->identifier_level, 0);
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(sp[-1]) != T_ARRAY)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Bad return type from o->_indices()\n");
a0f9071997-01-26Fredrik Hübinette (Hubbe)  a=sp[-1].u.array; sp--;
5d35781999-10-24Henrik Grubbström (Grubba)  dmalloc_touch_svalue(sp);
4a66491995-11-13Per Hedbor  } return a; }
9273742008-05-29Henrik Grubbström (Grubba) PMOD_EXPORT struct array *object_values(struct object *o, int inherit_number)
4a66491995-11-13Per Hedbor { struct program *p;
9273742008-05-29Henrik Grubbström (Grubba)  struct inherit *inh;
4a66491995-11-13Per Hedbor  struct array *a;
9273742008-05-29Henrik Grubbström (Grubba)  int fun;
4a66491995-11-13Per Hedbor  int e; p=o->prog; if(!p)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("values() on destructed object.\n");
4a66491995-11-13Per Hedbor 
9273742008-05-29Henrik Grubbström (Grubba)  p = (inh = p->inherits + inherit_number)->prog; if((fun = FIND_LFUN(p, LFUN__VALUES)) == -1)
4a66491995-11-13Per Hedbor  {
2523ce2003-04-28Martin Stjernholm  TYPE_FIELD types = 0;
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  a=allocate_array_no_init(p->num_identifier_index,0); for(e=0;e<(int)p->num_identifier_index;e++)
a0f9071997-01-26Fredrik Hübinette (Hubbe)  {
9273742008-05-29Henrik Grubbström (Grubba)  low_object_index_no_free(ITEM(a)+e, o, p->identifier_index[e] + inh->identifier_level);
017b572011-10-28Henrik Grubbström (Grubba)  types |= 1 << TYPEOF(ITEM(a)[e]);
a0f9071997-01-26Fredrik Hübinette (Hubbe)  }
2523ce2003-04-28Martin Stjernholm  a->type_field = types;
a0f9071997-01-26Fredrik Hübinette (Hubbe)  }else{
9273742008-05-29Henrik Grubbström (Grubba)  apply_low(o, fun + inh->identifier_level, 0);
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(sp[-1]) != T_ARRAY)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Bad return type from o->_values()\n");
a0f9071997-01-26Fredrik Hübinette (Hubbe)  a=sp[-1].u.array; sp--;
5d35781999-10-24Henrik Grubbström (Grubba)  dmalloc_touch_svalue(sp);
4a66491995-11-13Per Hedbor  } return a; }
a22fdc1996-02-19Fredrik Hübinette (Hubbe) 
7195af2011-01-15Henrik Grubbström (Grubba) PMOD_EXPORT struct array *object_types(struct object *o, int inherit_number) { struct program *p; struct inherit *inh; struct array *a; int fun; int e; p=o->prog; if(!p) Pike_error("types() on destructed object.\n"); p = (inh = p->inherits + inherit_number)->prog; if((fun = low_find_lfun(p, LFUN__TYPES)) == -1) { if ((fun = FIND_LFUN(p, LFUN__VALUES)) != -1) { /* Some compat for the case where lfun::_values() is overloaded, * but not lfun::_types(). */ a = object_values(o, inherit_number); for(e=0;e<a->size;e++) { struct pike_type *t = get_type_of_svalue(ITEM(a) + e); free_svalue(ITEM(a) + e);
017b572011-10-28Henrik Grubbström (Grubba)  SET_SVAL(ITEM(a)[e], PIKE_T_TYPE, 0, type, t);
7195af2011-01-15Henrik Grubbström (Grubba)  } a->type_field = BIT_TYPE; return a; } a=allocate_array_no_init(p->num_identifier_index,0); for(e=0;e<(int)p->num_identifier_index;e++) { struct identifier *id = ID_FROM_INT(p,p->identifier_index[e]);
017b572011-10-28Henrik Grubbström (Grubba)  SET_SVAL(ITEM(a)[e], PIKE_T_TYPE, 0, type, id->type);
7195af2011-01-15Henrik Grubbström (Grubba)  } a->type_field = BIT_TYPE; }else{ apply_low(o, fun + inh->identifier_level, 0);
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(sp[-1]) != T_ARRAY)
7195af2011-01-15Henrik Grubbström (Grubba)  Pike_error("Bad return type from o->_types()\n"); a=sp[-1].u.array; sp--; dmalloc_touch_svalue(sp); } return a; }
5e83442008-05-11Martin Stjernholm 
1eb9852008-05-11Martin Stjernholm PMOD_EXPORT void visit_object (struct object *o, int action)
5e83442008-05-11Martin Stjernholm { struct program *p = o->prog; if (o->next == o) return; /* Fake object used by compiler */ switch (action) { #ifdef PIKE_DEBUG default: Pike_fatal ("Unknown visit action %d.\n", action); case VISIT_NORMAL: case VISIT_COMPLEX_ONLY: break; #endif case VISIT_COUNT_BYTES: mc_counted_bytes += sizeof (struct object); if (p) mc_counted_bytes += p->storage_needed; break; } if (PIKE_OBJ_INITED (o)) { struct pike_frame *pike_frame = NULL; struct inherit *inh = p->inherits; char *storage = o->storage; int e; debug_malloc_touch (p); debug_malloc_touch (o); debug_malloc_touch (storage); visit_program_ref (p, REF_TYPE_NORMAL); for (e = p->num_inherits - 1; e >= 0; e--) { struct program *inh_prog = inh[e].prog; unsigned INT16 *inh_prog_var_idxs = inh_prog->variable_index; struct identifier *inh_prog_ids = inh_prog->identifiers; char *inh_storage = storage + inh[e].storage_offset; int q, num_vars = (int) inh_prog->num_variable_index; for (q = 0; q < num_vars; q++) { int d = inh_prog_var_idxs[q]; struct identifier *id = inh_prog_ids + d; int id_flags = id->identifier_flags; int rtt = id->run_time_type; void *var; union anything *u; if (IDENTIFIER_IS_ALIAS (id_flags)) continue; var = inh_storage + id->func.offset; u = (union anything *) var; #ifdef DEBUG_MALLOC
4a93e82013-06-11Henrik Grubbström (Grubba)  if (REFCOUNTED_TYPE(rtt))
5e83442008-05-11Martin Stjernholm  debug_malloc_touch (u->ptr); #endif switch (rtt) { case T_MIXED: { struct svalue *s = (struct svalue *) var; dmalloc_touch_svalue (s);
017b572011-10-28Henrik Grubbström (Grubba)  if ((TYPEOF(*s) != T_OBJECT && TYPEOF(*s) != T_FUNCTION) ||
5e83442008-05-11Martin Stjernholm  s->u.object != o || !(id_flags & IDENTIFIER_NO_THIS_REF)) visit_svalue (s, REF_TYPE_NORMAL); break; } case T_ARRAY: if (u->array) visit_array_ref (u->array, REF_TYPE_NORMAL); break; case T_MAPPING: if (u->mapping) visit_mapping_ref (u->mapping, REF_TYPE_NORMAL); break; case T_MULTISET: if (u->multiset) visit_multiset_ref (u->multiset, REF_TYPE_NORMAL); break; case T_PROGRAM: if (u->program) visit_program_ref (u->program, REF_TYPE_NORMAL); break; case T_OBJECT: if (u->object && (u->object != o || !(id_flags & IDENTIFIER_NO_THIS_REF))) visit_object_ref (u->object, REF_TYPE_NORMAL); break; case T_STRING: if (u->string && !(action & VISIT_COMPLEX_ONLY)) visit_string_ref (u->string, REF_TYPE_NORMAL); break; case T_TYPE: if (u->type && !(action & VISIT_COMPLEX_ONLY)) visit_type_ref (u->type, REF_TYPE_NORMAL); break; #ifdef PIKE_DEBUG case PIKE_T_GET_SET:
2e1a6a2008-05-29Henrik Grubbström (Grubba)  case PIKE_T_FREE:
5e83442008-05-11Martin Stjernholm  case T_INT: case T_FLOAT: break; default: Pike_fatal ("Invalid runtime type %d.\n", rtt); #endif } } if (inh_prog->event_handler) { if (!pike_frame) PUSH_FRAME2 (o, p); SET_FRAME_CONTEXT (inh + e); inh_prog->event_handler (PROG_EVENT_GC_RECURSE); } } if (pike_frame) POP_FRAME2(); /* Strong ref follows. It must be last. */ if (p->flags & PROGRAM_USES_PARENT) if (PARENT_INFO (o)->parent) visit_object_ref (PARENT_INFO (o)->parent, REF_TYPE_STRONG); } }
4420d92010-04-19Martin Stjernholm PMOD_EXPORT void visit_function (const struct svalue *s, int ref_type)
5e83442008-05-11Martin Stjernholm { #ifdef PIKE_DEBUG
017b572011-10-28Henrik Grubbström (Grubba)  if (TYPEOF(*s) != T_FUNCTION)
5e83442008-05-11Martin Stjernholm  Pike_fatal ("Should only be called for a function svalue.\n"); #endif
017b572011-10-28Henrik Grubbström (Grubba)  if (SUBTYPEOF(*s) == FUNCTION_BUILTIN)
5e83442008-05-11Martin Stjernholm  /* Could avoid this if we had access to the action from the caller * and check if it's VISIT_COMPLEX_ONLY. However, visit_callable * will only return first thing. */ visit_callable_ref (s->u.efun, ref_type); else visit_object_ref (s->u.object, ref_type); }
ad8d052008-05-02Martin Stjernholm static void gc_check_object(struct object *o);
a22fdc1996-02-19Fredrik Hübinette (Hubbe) 
fa8c692000-11-30Fredrik Hübinette (Hubbe) PMOD_EXPORT void gc_mark_object_as_referenced(struct object *o)
c94c371996-03-28Fredrik Hübinette (Hubbe) {
a5866c2000-04-13Henrik Grubbström (Grubba)  debug_malloc_touch(o);
648a1a2000-06-22Fredrik Hübinette (Hubbe)  debug_malloc_touch(o->storage);
a5866c2000-04-13Henrik Grubbström (Grubba) 
613c342009-11-28Martin Stjernholm  if(gc_mark(o, T_OBJECT)) {
619bb82003-09-24Martin Stjernholm  if(o->next == o) return; /* Fake object used by compiler */
e1a35e2003-09-08Martin Stjernholm  GC_ENTER (o, T_OBJECT) { int e;
ad8d052008-05-02Martin Stjernholm  struct program *p = o->prog;
e1a35e2003-09-08Martin Stjernholm  if (o == gc_mark_object_pos) gc_mark_object_pos = o->next; if (o == gc_internal_object) gc_internal_object = o->next; else { DOUBLEUNLINK(first_object, o); DOUBLELINK(first_object, o); /* Linked in first. */ }
e2d9e62000-06-10Martin Stjernholm 
ad8d052008-05-02Martin Stjernholm  if(p && PIKE_OBJ_INITED(o)) {
619bb82003-09-24Martin Stjernholm  debug_malloc_touch(p);
d4828c1997-07-17Fredrik Hübinette (Hubbe) 
619bb82003-09-24Martin Stjernholm  gc_mark_program_as_referenced (p);
a5866c2000-04-13Henrik Grubbström (Grubba) 
619bb82003-09-24Martin Stjernholm  if(o->prog->flags & PROGRAM_USES_PARENT) if(PARENT_INFO(o)->parent) gc_mark_object_as_referenced(PARENT_INFO(o)->parent);
0455ff2003-03-30Martin Stjernholm 
fa93a52008-02-28Henrik Grubbström (Grubba)  LOW_PUSH_FRAME(o, p);
d4828c1997-07-17Fredrik Hübinette (Hubbe) 
619bb82003-09-24Martin Stjernholm  for(e=p->num_inherits-1; e>=0; e--) { int q;
c94c371996-03-28Fredrik Hübinette (Hubbe) 
fa93a52008-02-28Henrik Grubbström (Grubba)  LOW_SET_FRAME_CONTEXT(p->inherits + e);
d4828c1997-07-17Fredrik Hübinette (Hubbe) 
fa93a52008-02-28Henrik Grubbström (Grubba)  for(q=0;q<(int)pike_frame->context->prog->num_variable_index;q++)
619bb82003-09-24Martin Stjernholm  {
fa93a52008-02-28Henrik Grubbström (Grubba)  int d=pike_frame->context->prog->variable_index[q]; struct identifier *id = pike_frame->context->prog->identifiers + d;
619bb82003-09-24Martin Stjernholm  int id_flags = id->identifier_flags; int rtt = id->run_time_type;
eff2b02001-07-03Henrik Grubbström (Grubba) 
2e1a6a2008-05-29Henrik Grubbström (Grubba)  if (IDENTIFIER_IS_ALIAS(id_flags) || (rtt == PIKE_T_GET_SET) || (rtt == PIKE_T_FREE))
417e952006-10-27Henrik Grubbström (Grubba)  continue;
c94c371996-03-28Fredrik Hübinette (Hubbe) 
619bb82003-09-24Martin Stjernholm  if(rtt == T_MIXED) { struct svalue *s; s=(struct svalue *)(pike_frame->current_storage + id->func.offset); dmalloc_touch_svalue(s);
017b572011-10-28Henrik Grubbström (Grubba)  if ((TYPEOF(*s) != T_OBJECT && TYPEOF(*s) != T_FUNCTION) || s->u.object != o || !(id_flags & IDENTIFIER_NO_THIS_REF))
619bb82003-09-24Martin Stjernholm  gc_mark_svalues(s, 1); }else{ union anything *u; u=(union anything *)(pike_frame->current_storage + id->func.offset);
a96ce92000-04-19Fredrik Hübinette (Hubbe) #ifdef DEBUG_MALLOC
4a93e82013-06-11Henrik Grubbström (Grubba)  if (REFCOUNTED_TYPE(rtt)) debug_malloc_touch(u->refs);
a96ce92000-04-19Fredrik Hübinette (Hubbe) #endif
619bb82003-09-24Martin Stjernholm  if (rtt != T_OBJECT || u->object != o || !(id_flags & IDENTIFIER_NO_THIS_REF)) gc_mark_short_svalue(u, rtt); }
e1a35e2003-09-08Martin Stjernholm  }
a9ae572004-04-04Martin Stjernholm 
fa93a52008-02-28Henrik Grubbström (Grubba)  if(pike_frame->context->prog->event_handler) pike_frame->context->prog->event_handler(PROG_EVENT_GC_RECURSE);
a9ae572004-04-04Martin Stjernholm 
619bb82003-09-24Martin Stjernholm  LOW_UNSET_FRAME_CONTEXT();
c94c371996-03-28Fredrik Hübinette (Hubbe)  }
619bb82003-09-24Martin Stjernholm  LOW_POP_FRAME();
c94c371996-03-28Fredrik Hübinette (Hubbe)  }
e1a35e2003-09-08Martin Stjernholm  } GC_LEAVE;
619bb82003-09-24Martin Stjernholm  }
a22fdc1996-02-19Fredrik Hübinette (Hubbe) }
fa8c692000-11-30Fredrik Hübinette (Hubbe) PMOD_EXPORT void real_gc_cycle_check_object(struct object *o, int weak)
e2d9e62000-06-10Martin Stjernholm {
ab27db2001-01-17Martin Stjernholm  if(o->next == o) return; /* Fake object used by compiler */
45d87e2000-07-18Martin Stjernholm  GC_CYCLE_ENTER_OBJECT(o, weak) { int e; struct program *p = o->prog;
e2d9e62000-06-10Martin Stjernholm 
c2be512001-03-21Fredrik Hübinette (Hubbe)  if (p && PIKE_OBJ_INITED(o)) {
e2d9e62000-06-10Martin Stjernholm #if 0
45d87e2000-07-18Martin Stjernholm  struct object *o2; for (o2 = gc_internal_object; o2 && o2 != o; o2 = o2->next) {}
5aad932002-08-15Marcus Comstedt  if (!o2) Pike_fatal("Object not on gc_internal_object list.\n");
e2d9e62000-06-10Martin Stjernholm #endif
fa93a52008-02-28Henrik Grubbström (Grubba)  LOW_PUSH_FRAME(o, p);
52b2c42000-07-02Martin Stjernholm 
45d87e2000-07-18Martin Stjernholm  for(e=p->num_inherits-1; e>=0; e--) { int q;
e2d9e62000-06-10Martin Stjernholm 
fa93a52008-02-28Henrik Grubbström (Grubba)  LOW_SET_FRAME_CONTEXT(p->inherits + e);
e2d9e62000-06-10Martin Stjernholm 
fa93a52008-02-28Henrik Grubbström (Grubba)  for(q=0;q<(int)pike_frame->context->prog->num_variable_index;q++)
e2d9e62000-06-10Martin Stjernholm  {
fa93a52008-02-28Henrik Grubbström (Grubba)  int d=pike_frame->context->prog->variable_index[q]; struct identifier *id = pike_frame->context->prog->identifiers + d;
e0d6f52003-02-13Martin Stjernholm  int id_flags = id->identifier_flags; int rtt = id->run_time_type;
45d87e2000-07-18Martin Stjernholm 
2e1a6a2008-05-29Henrik Grubbström (Grubba)  if (IDENTIFIER_IS_ALIAS(id_flags) || (rtt == PIKE_T_GET_SET) || (rtt == PIKE_T_FREE))
417e952006-10-27Henrik Grubbström (Grubba)  continue;
eff2b02001-07-03Henrik Grubbström (Grubba) 
e0d6f52003-02-13Martin Stjernholm  if(rtt == T_MIXED)
45d87e2000-07-18Martin Stjernholm  { struct svalue *s;
e0d6f52003-02-13Martin Stjernholm  s=(struct svalue *)(pike_frame->current_storage + id->func.offset);
45d87e2000-07-18Martin Stjernholm  dmalloc_touch_svalue(s);
017b572011-10-28Henrik Grubbström (Grubba)  if ((TYPEOF(*s) != T_OBJECT && TYPEOF(*s) != T_FUNCTION) || s->u.object != o || !(id_flags & IDENTIFIER_NO_THIS_REF))
8d4faf2003-02-10Martin Stjernholm  gc_cycle_check_svalues(s, 1);
45d87e2000-07-18Martin Stjernholm  }else{ union anything *u;
e0d6f52003-02-13Martin Stjernholm  u=(union anything *)(pike_frame->current_storage + id->func.offset);
e2d9e62000-06-10Martin Stjernholm #ifdef DEBUG_MALLOC
4a93e82013-06-11Henrik Grubbström (Grubba)  if (REFCOUNTED_TYPE(rtt)) debug_malloc_touch(u->refs);
e2d9e62000-06-10Martin Stjernholm #endif
e0d6f52003-02-13Martin Stjernholm  if (rtt != T_OBJECT || u->object != o || !(id_flags & IDENTIFIER_NO_THIS_REF))
8d4faf2003-02-10Martin Stjernholm  gc_cycle_check_short_svalue(u, rtt);
45d87e2000-07-18Martin Stjernholm  }
e2d9e62000-06-10Martin Stjernholm  }
a9ae572004-04-04Martin Stjernholm 
fa93a52008-02-28Henrik Grubbström (Grubba)  if(pike_frame->context->prog->event_handler) pike_frame->context->prog->event_handler(PROG_EVENT_GC_RECURSE);
a9ae572004-04-04Martin Stjernholm 
45d87e2000-07-18Martin Stjernholm  LOW_UNSET_FRAME_CONTEXT();
e2d9e62000-06-10Martin Stjernholm  }
45d87e2000-07-18Martin Stjernholm  LOW_POP_FRAME();
e2d9e62000-06-10Martin Stjernholm 
b5f2732003-03-30Martin Stjernholm  /* Even though it's essential that the program isn't freed * before the object, it doesn't need a strong link. That since * programs can't be destructed before they run out of * references. */ gc_cycle_check_program (p, 0); /* Strong ref follows. It must be last. */
f3c7152001-04-14Fredrik Hübinette (Hubbe)  if(o->prog->flags & PROGRAM_USES_PARENT) if(PARENT_INFO(o)->parent) gc_cycle_check_object(PARENT_INFO(o)->parent, -1);
45d87e2000-07-18Martin Stjernholm  }
e2d9e62000-06-10Martin Stjernholm  } GC_CYCLE_LEAVE; }
ad8d052008-05-02Martin Stjernholm static void gc_check_object(struct object *o)
a22fdc1996-02-19Fredrik Hübinette (Hubbe) {
20513c2000-04-12Fredrik Hübinette (Hubbe)  int e; struct program *p;
e444911998-04-05Fredrik Hübinette (Hubbe) 
e1a35e2003-09-08Martin Stjernholm  GC_ENTER (o, T_OBJECT) { if((p=o->prog) && PIKE_OBJ_INITED(o)) { debug_malloc_touch(p); debug_gc_check (p, " as the program of an object");
0455ff2003-03-30Martin Stjernholm 
e1a35e2003-09-08Martin Stjernholm  if(p->flags & PROGRAM_USES_PARENT && PARENT_INFO(o)->parent) debug_gc_check (PARENT_INFO(o)->parent, " as parent of an object");
a5866c2000-04-13Henrik Grubbström (Grubba) 
fa93a52008-02-28Henrik Grubbström (Grubba)  LOW_PUSH_FRAME(o, p);
20513c2000-04-12Fredrik Hübinette (Hubbe) 
e1a35e2003-09-08Martin Stjernholm  for(e=p->num_inherits-1; e>=0; e--)
c94c371996-03-28Fredrik Hübinette (Hubbe)  {
e1a35e2003-09-08Martin Stjernholm  int q;
fa93a52008-02-28Henrik Grubbström (Grubba)  LOW_SET_FRAME_CONTEXT(p->inherits + e);
e1a35e2003-09-08Martin Stjernholm 
fa93a52008-02-28Henrik Grubbström (Grubba)  for(q=0;q<(int)pike_frame->context->prog->num_variable_index;q++)
e1a35e2003-09-08Martin Stjernholm  {
fa93a52008-02-28Henrik Grubbström (Grubba)  int d=pike_frame->context->prog->variable_index[q]; struct identifier *id = pike_frame->context->prog->identifiers + d;
e1a35e2003-09-08Martin Stjernholm  int id_flags = id->identifier_flags; int rtt = id->run_time_type;
e444911998-04-05Fredrik Hübinette (Hubbe) 
2e1a6a2008-05-29Henrik Grubbström (Grubba)  if (IDENTIFIER_IS_ALIAS(id_flags) || (rtt == PIKE_T_GET_SET) || (rtt == PIKE_T_FREE))
417e952006-10-27Henrik Grubbström (Grubba)  continue;
eff2b02001-07-03Henrik Grubbström (Grubba) 
e1a35e2003-09-08Martin Stjernholm  if(rtt == T_MIXED) { struct svalue *s; s=(struct svalue *)(pike_frame->current_storage + id->func.offset); dmalloc_touch_svalue(s);
017b572011-10-28Henrik Grubbström (Grubba)  if ((TYPEOF(*s) != T_OBJECT && TYPEOF(*s) != T_FUNCTION) || s->u.object != o || !(id_flags & IDENTIFIER_NO_THIS_REF))
e1a35e2003-09-08Martin Stjernholm  gc_check_svalues(s, 1); }else{ union anything *u; u=(union anything *)(pike_frame->current_storage + id->func.offset);
a96ce92000-04-19Fredrik Hübinette (Hubbe) #ifdef DEBUG_MALLOC
4a93e82013-06-11Henrik Grubbström (Grubba)  if (REFCOUNTED_TYPE(rtt)) debug_malloc_touch(u->refs);
a96ce92000-04-19Fredrik Hübinette (Hubbe) #endif
e1a35e2003-09-08Martin Stjernholm  if (rtt != T_OBJECT || u->object != o || !(id_flags & IDENTIFIER_NO_THIS_REF)) gc_check_short_svalue(u, rtt); }
c94c371996-03-28Fredrik Hübinette (Hubbe)  }
a9ae572004-04-04Martin Stjernholm 
fa93a52008-02-28Henrik Grubbström (Grubba)  if(pike_frame->context->prog->event_handler) pike_frame->context->prog->event_handler(PROG_EVENT_GC_CHECK);
e942a72000-04-15Fredrik Hübinette (Hubbe) 
a9ae572004-04-04Martin Stjernholm  LOW_UNSET_FRAME_CONTEXT();
e1a35e2003-09-08Martin Stjernholm  } LOW_POP_FRAME();
c94c371996-03-28Fredrik Hübinette (Hubbe)  }
e1a35e2003-09-08Martin Stjernholm  } GC_LEAVE;
20513c2000-04-12Fredrik Hübinette (Hubbe) }
e2d9e62000-06-10Martin Stjernholm unsigned gc_touch_all_objects(void)
20513c2000-04-12Fredrik Hübinette (Hubbe) {
e2d9e62000-06-10Martin Stjernholm  unsigned n = 0;
e942a72000-04-15Fredrik Hübinette (Hubbe)  struct object *o;
e2d9e62000-06-10Martin Stjernholm  if (first_object && first_object->prev)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Error in object link list.\n");
7bf6232000-04-23Martin Stjernholm  for (o = first_object; o; o = o->next) {
e2d9e62000-06-10Martin Stjernholm  debug_gc_touch(o); n++; if (o->next && o->next->prev != o)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Error in object link list.\n");
e2d9e62000-06-10Martin Stjernholm  }
aec5af2001-01-22Martin Stjernholm  for (o = objects_to_destruct; o; o = o->next) n++;
7bf6232000-04-23Martin Stjernholm  return n; }
20513c2000-04-12Fredrik Hübinette (Hubbe) 
7bf6232000-04-23Martin Stjernholm void gc_check_all_objects(void) { struct object *o;
e942a72000-04-15Fredrik Hübinette (Hubbe)  for(o=first_object;o;o=o->next)
20513c2000-04-12Fredrik Hübinette (Hubbe)  gc_check_object(o);
c94c371996-03-28Fredrik Hübinette (Hubbe) }
be478c1997-08-30Henrik Grubbström (Grubba) void gc_mark_all_objects(void)
c94c371996-03-28Fredrik Hübinette (Hubbe) {
e2d9e62000-06-10Martin Stjernholm  gc_mark_object_pos = gc_internal_object; while (gc_mark_object_pos) { struct object *o = gc_mark_object_pos; gc_mark_object_pos = o->next;
d348a72000-07-03Martin Stjernholm  if(o->refs && gc_is_referenced(o)) /* Refs check since objects without refs are left around during * gc by schedule_really_free_object(). */
c94c371996-03-28Fredrik Hübinette (Hubbe)  gc_mark_object_as_referenced(o);
e2d9e62000-06-10Martin Stjernholm  }
e942a72000-04-15Fredrik Hübinette (Hubbe) 
c318612000-04-21Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
e2d9e62000-06-10Martin Stjernholm  if(d_flag) { struct object *o;
c318612000-04-21Fredrik Hübinette (Hubbe)  for(o=objects_to_destruct;o;o=o->next) debug_malloc_touch(o);
e2d9e62000-06-10Martin Stjernholm  }
c318612000-04-21Fredrik Hübinette (Hubbe) #endif
c94c371996-03-28Fredrik Hübinette (Hubbe) }
e2d9e62000-06-10Martin Stjernholm void gc_cycle_check_all_objects(void)
c94c371996-03-28Fredrik Hübinette (Hubbe) {
e2d9e62000-06-10Martin Stjernholm  struct object *o; for (o = gc_internal_object; o; o = o->next) {
45d87e2000-07-18Martin Stjernholm  real_gc_cycle_check_object(o, 0); gc_cycle_run_queue();
94851f2000-04-20Martin Stjernholm  } }
45d87e2000-07-18Martin Stjernholm void gc_zap_ext_weak_refs_in_objects(void) { gc_mark_object_pos = first_object; while (gc_mark_object_pos != gc_internal_object && gc_ext_weak_refs) { struct object *o = gc_mark_object_pos; gc_mark_object_pos = o->next; if (o->refs) gc_mark_object_as_referenced(o); }
e1a35e2003-09-08Martin Stjernholm  gc_mark_discard_queue();
45d87e2000-07-18Martin Stjernholm }
88cf4f2003-01-11Martin Stjernholm size_t gc_free_all_unreferenced_objects(void)
94851f2000-04-20Martin Stjernholm { struct object *o,*next;
a1b3872003-01-11Martin Stjernholm  size_t unreferenced = 0;
09f2882005-02-09Martin Stjernholm  enum object_destruct_reason reason = #ifdef DO_PIKE_CLEANUP gc_destruct_everything ? DESTRUCT_CLEANUP : #endif DESTRUCT_GC;
94851f2000-04-20Martin Stjernholm 
e2d9e62000-06-10Martin Stjernholm  for(o=gc_internal_object; o; o=next)
a22fdc1996-02-19Fredrik Hübinette (Hubbe)  {
9da7322000-07-03Martin Stjernholm  if(gc_do_free(o))
624d091996-02-24Fredrik Hübinette (Hubbe)  {
e2d9e62000-06-10Martin Stjernholm  /* Got an extra ref from gc_cycle_pop_object(). */
87c7f92000-04-19Martin Stjernholm #ifdef PIKE_DEBUG
99cce52007-05-26Martin Stjernholm  if (gc_object_is_live (o) &&
e2d9e62000-06-10Martin Stjernholm  !find_destroy_called_mark(o)) gc_fatal(o,0,"Can't free a live object in gc_free_all_unreferenced_objects().\n");
87c7f92000-04-19Martin Stjernholm #endif
54717e2001-06-28Fredrik Hübinette (Hubbe)  debug_malloc_touch(o);
09f2882005-02-09Martin Stjernholm  destruct_object (o, reason);
e2d9e62000-06-10Martin Stjernholm  gc_free_extra_ref(o);
69ee4b2000-04-06Fredrik Hübinette (Hubbe)  SET_NEXT_AND_FREE(o,free_object);
624d091996-02-24Fredrik Hübinette (Hubbe)  }else{ next=o->next; }
a1b3872003-01-11Martin Stjernholm  unreferenced++;
a22fdc1996-02-19Fredrik Hübinette (Hubbe)  }
88cf4f2003-01-11Martin Stjernholm 
a1b3872003-01-11Martin Stjernholm  return unreferenced;
a22fdc1996-02-19Fredrik Hübinette (Hubbe) }
a5787d1999-03-03Fredrik Hübinette (Hubbe) struct magic_index_struct {
a005eb1999-03-04Fredrik Hübinette (Hubbe)  struct inherit *inherit;
a5787d1999-03-03Fredrik Hübinette (Hubbe)  struct object *o; };
60d9872000-03-23Fredrik Hübinette (Hubbe) #define MAGIC_THIS ((struct magic_index_struct *)(CURRENT_STORAGE))
648a1a2000-06-22Fredrik Hübinette (Hubbe) #define MAGIC_O2S(o) ((struct magic_index_struct *)(o->storage))
a5787d1999-03-03Fredrik Hübinette (Hubbe)  struct program *magic_index_program=0; struct program *magic_set_index_program=0;
cbe1132001-12-16Martin Stjernholm struct program *magic_indices_program=0; struct program *magic_values_program=0;
7195af2011-01-15Henrik Grubbström (Grubba) struct program *magic_types_program=0;
a5787d1999-03-03Fredrik Hübinette (Hubbe) 
624f571999-03-11Fredrik Hübinette (Hubbe) void push_magic_index(struct program *type, int inherit_no, int parent_level)
a5787d1999-03-03Fredrik Hübinette (Hubbe) {
342fef2000-08-23Fredrik Hübinette (Hubbe)  struct external_variable_context loc; struct object *magic;
a5787d1999-03-03Fredrik Hübinette (Hubbe) 
e8e2532009-08-25Henrik Grubbström (Grubba)  loc.o = Pike_fp->current_object;
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  if(!loc.o) Pike_error("Illegal magic index call.\n");
a005eb1999-03-04Fredrik Hübinette (Hubbe) 
e8e2532009-08-25Henrik Grubbström (Grubba)  loc.parent_identifier = Pike_fp->fun; loc.inherit = Pike_fp->context;
342fef2000-08-23Fredrik Hübinette (Hubbe)  find_external_context(&loc, parent_level);
624f571999-03-11Fredrik Hübinette (Hubbe) 
28553d2003-08-03Martin Stjernholm  if (!loc.o->prog) Pike_error ("Cannot index in destructed parent object.\n");
624f571999-03-11Fredrik Hübinette (Hubbe)  magic=low_clone(type);
342fef2000-08-23Fredrik Hübinette (Hubbe)  add_ref(MAGIC_O2S(magic)->o=loc.o); MAGIC_O2S(magic)->inherit = loc.inherit + inherit_no;
6369f61999-03-11Fredrik Hübinette (Hubbe) #ifdef DEBUG
1dec862009-08-18Stephen R. van den Berg  if(loc.inherit + inherit_no >= loc.o->prog->inherits + loc.o->prog->num_inherits)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Magic index blahonga!\n");
6369f61999-03-11Fredrik Hübinette (Hubbe) #endif
624f571999-03-11Fredrik Hübinette (Hubbe)  push_object(magic);
a5787d1999-03-03Fredrik Hübinette (Hubbe) }
47251d2002-12-11Henrik Grubbström (Grubba) /*! @namespace ::
d345e92002-12-20Henrik Grubbström (Grubba)  *! *! Symbols implicitly inherited from the virtual base class. *! *! These symbols exist mainly to simplify implementation of *! the corresponding lfuns. *! *! @seealso *! @[lfun::]
9683052001-10-28Martin Nilsson  */
c80f622012-04-29Henrik Grubbström (Grubba) /* Historical API notes: * * In Pike 7.3.14 to 7.9.5 the context and access arguments were instead * represented by a single type argument. * * The type argument to the magic index functions is intentionally
1ba3e52001-12-19Martin Stjernholm  * undocumented since I'm not sure this API is satisfactory. The * argument would be explained as follows. /mast * * The indexing normally involves the externally accessable
9779872008-06-28Martin Stjernholm  * identifiers (i.e. those which aren't protected or private) in the
1ba3e52001-12-19Martin Stjernholm  * current class and any inherited classes. If @[type] is 1 then * locally accessible identifiers are indexed too. If @[type] is 2 * then all externally accessible identifiers in the object, i.e. also
0489c72002-08-07Henrik Grubbström (Grubba)  * those in inheriting classes, are indexed. And if @[type] is 3 * then all locally accessible identifiers in the object, i.e. also * those in inheriting classes, are indexed. */
1ba3e52001-12-19Martin Stjernholm 
c80f622012-04-29Henrik Grubbström (Grubba) /*! @decl mixed ::`->(string index, object|void context, int|void access)
959b952001-02-06Henrik Grubbström (Grubba)  *! *! Builtin arrow operator. *!
c80f622012-04-29Henrik Grubbström (Grubba)  *! @param index *! Symbol in @[context] to access. *! *! @param context *! Context in the current object to start the search from. *! If @expr{UNDEFINED@} or left out, @expr{this_program::this@} *! will be used (ie start at the current context and ignore *! any overloaded symbols). *! *! @param access *! Access permission override. One of the following: *! @int *! @value 0 *! @value UNDEFINED *! See only public symbols. *! @value 1 *! See protected symbols as well. *! @endint *!
959b952001-02-06Henrik Grubbström (Grubba)  *! This function indexes the current object with the string @[index]. *! This is useful when the arrow operator has been overloaded. *! *! @seealso *! @[::`->=()] */
a5787d1999-03-03Fredrik Hübinette (Hubbe) static void f_magic_index(INT32 args) {
c80f622012-04-29Henrik Grubbström (Grubba)  struct inherit *inherit = NULL;
1ba3e52001-12-19Martin Stjernholm  int type = 0, f;
a5787d1999-03-03Fredrik Hübinette (Hubbe)  struct pike_string *s;
c80f622012-04-29Henrik Grubbström (Grubba)  struct object *o = NULL;
a5787d1999-03-03Fredrik Hübinette (Hubbe) 
c80f622012-04-29Henrik Grubbström (Grubba)  switch(args) {
1ba3e52001-12-19Martin Stjernholm  default:
c80f622012-04-29Henrik Grubbström (Grubba)  case 3: if (TYPEOF(sp[2-args]) != T_INT)
017b572011-10-28Henrik Grubbström (Grubba)  SIMPLE_BAD_ARG_ERROR ("::`->", 2, "void|int");
c80f622012-04-29Henrik Grubbström (Grubba)  type = sp[2-args].u.integer & 1; /* FALL THROUGH */ case 2: if (TYPEOF(sp[1-args]) == T_INT) { /* Compat with old-style args. */ type |= (sp[1-args].u.integer & 1); if (sp[1-args].u.integer & 2) { if(!(o=MAGIC_THIS->o)) Pike_error("Magic index error\n"); if(!o->prog) Pike_error("::`-> on destructed object.\n"); inherit = o->prog->inherits + 0; } } else if (TYPEOF(sp[1-args]) == T_OBJECT) { o = sp[1-args].u.object; if (o != MAGIC_THIS->o) Pike_error("::`-> context is not the current object.\n"); if(!o->prog) Pike_error("::`-> on destructed object.\n"); inherit = o->prog->inherits + SUBTYPEOF(sp[1-args]); } else { SIMPLE_BAD_ARG_ERROR ("::`->", 2, "void|object|int"); }
1ba3e52001-12-19Martin Stjernholm  /* FALL THROUGH */ case 1:
017b572011-10-28Henrik Grubbström (Grubba)  if (TYPEOF(sp[-args]) != T_STRING) SIMPLE_BAD_ARG_ERROR ("::`->", 1, "string");
1ba3e52001-12-19Martin Stjernholm  s = sp[-args].u.string; break; case 0: SIMPLE_TOO_FEW_ARGS_ERROR ("::`->", 1); }
a5787d1999-03-03Fredrik Hübinette (Hubbe) 
c80f622012-04-29Henrik Grubbström (Grubba)  if(!o && !(o = MAGIC_THIS->o))
a4a1722000-12-05Per Hedbor  Pike_error("Magic index error\n");
a5787d1999-03-03Fredrik Hübinette (Hubbe) 
6369f61999-03-11Fredrik Hübinette (Hubbe)  if(!o->prog)
cbe1132001-12-16Martin Stjernholm  Pike_error("::`-> on destructed object.\n");
6369f61999-03-11Fredrik Hübinette (Hubbe) 
c80f622012-04-29Henrik Grubbström (Grubba)  if (!inherit) { inherit = MAGIC_THIS->inherit; } /* NB: We could use really_low_find_shared_string_identifier() * in both cases, but we get the added benefit of the * identifier cache if we use find_shared_string_identifier(). */ if (type) { f = really_low_find_shared_string_identifier(s, inherit->prog, SEE_PROTECTED); } else { f = find_shared_string_identifier(s, inherit->prog);
1ba3e52001-12-19Martin Stjernholm  }
a5787d1999-03-03Fredrik Hübinette (Hubbe) 
18942c2001-12-19Martin Stjernholm  pop_n_elems(args);
a5787d1999-03-03Fredrik Hübinette (Hubbe)  if(f<0) {
074dd12011-10-22Henrik Grubbström (Grubba)  push_undefined();
a5787d1999-03-03Fredrik Hübinette (Hubbe)  }else{ struct svalue sval; low_object_index_no_free(&sval,o,f+
a005eb1999-03-04Fredrik Hübinette (Hubbe)  inherit->identifier_level);
a5787d1999-03-03Fredrik Hübinette (Hubbe)  *sp=sval; sp++;
50ea682003-03-14Henrik Grubbström (Grubba)  dmalloc_touch_svalue(Pike_sp-1);
a5787d1999-03-03Fredrik Hübinette (Hubbe)  } }
c80f622012-04-29Henrik Grubbström (Grubba) /*! @decl void ::`->=(string index, mixed value, @ *! object|void context, int|void access)
959b952001-02-06Henrik Grubbström (Grubba)  *! *! Builtin arrow set operator. *!
c80f622012-04-29Henrik Grubbström (Grubba)  *! @param index *! Symbol in @[context] to change the value of. *! *! @param value *! The new value. *! *! @param context *! Context in the current object to start the search from. *! If @expr{UNDEFINED@} or left out, @expr{this_program::this@} *! will be used (ie start at the current context and ignore *! any overloaded symbols). *! *! @param access *! Access permission override. One of the following: *! @int *! @value 0 *! @value UNDEFINED *! See only public symbols. *! @value 1 *! See protected symbols as well. *! @endint *!
959b952001-02-06Henrik Grubbström (Grubba)  *! This function indexes the current object with the string @[index], *! and sets it to @[value]. *! This is useful when the arrow set operator has been overloaded. *! *! @seealso *! @[::`->()] */
a5787d1999-03-03Fredrik Hübinette (Hubbe) static void f_magic_set_index(INT32 args) {
1ba3e52001-12-19Martin Stjernholm  int type = 0, f;
a5787d1999-03-03Fredrik Hübinette (Hubbe)  struct pike_string *s;
c80f622012-04-29Henrik Grubbström (Grubba)  struct object *o = NULL;
a5787d1999-03-03Fredrik Hübinette (Hubbe)  struct svalue *val;
c80f622012-04-29Henrik Grubbström (Grubba)  struct inherit *inherit = NULL;
a5787d1999-03-03Fredrik Hübinette (Hubbe) 
1ba3e52001-12-19Martin Stjernholm  switch (args) { default:
c80f622012-04-29Henrik Grubbström (Grubba)  case 4: if (TYPEOF(sp[3-args]) != T_INT) SIMPLE_BAD_ARG_ERROR ("::`->=", 4, "void|int"); type = sp[3-args].u.integer & 1; /* FALL THROUGH */
1ba3e52001-12-19Martin Stjernholm  case 3:
c80f622012-04-29Henrik Grubbström (Grubba)  if (TYPEOF(sp[2-args]) == T_INT) { /* Compat with old-style args. */ type |= (sp[2-args].u.integer & 1); if (sp[2-args].u.integer & 2) { if(!(o=MAGIC_THIS->o)) Pike_error("Magic index error\n"); if(!o->prog) Pike_error("::`-> on destructed object.\n"); inherit = o->prog->inherits + 0; } } else if (TYPEOF(sp[2-args]) == T_OBJECT) { o = sp[2-args].u.object; if (o != MAGIC_THIS->o) Pike_error("::`->= context is not the current object.\n"); if(!o->prog) Pike_error("::`->= on destructed object.\n"); inherit = o->prog->inherits + SUBTYPEOF(sp[2-args]); } else { SIMPLE_BAD_ARG_ERROR ("::`->=", 3, "void|object|int"); }
1ba3e52001-12-19Martin Stjernholm  /* FALL THROUGH */ case 2: val = sp-args+1;
017b572011-10-28Henrik Grubbström (Grubba)  if (TYPEOF(sp[-args]) != T_STRING) SIMPLE_BAD_ARG_ERROR ("::`->=", 1, "string");
1ba3e52001-12-19Martin Stjernholm  s = sp[-args].u.string; break; case 1: case 0: SIMPLE_TOO_FEW_ARGS_ERROR ("::`->=", 2); }
a5787d1999-03-03Fredrik Hübinette (Hubbe) 
c80f622012-04-29Henrik Grubbström (Grubba)  if(!o && !(o = MAGIC_THIS->o))
a4a1722000-12-05Per Hedbor  Pike_error("Magic index error\n");
a5787d1999-03-03Fredrik Hübinette (Hubbe) 
6369f61999-03-11Fredrik Hübinette (Hubbe)  if(!o->prog)
cbe1132001-12-16Martin Stjernholm  Pike_error("::`->= on destructed object.\n");
6369f61999-03-11Fredrik Hübinette (Hubbe) 
c80f622012-04-29Henrik Grubbström (Grubba)  if (!inherit) { inherit = MAGIC_THIS->inherit; } /* NB: We could use really_low_find_shared_string_identifier() * in both cases, but we get the added benefit of the * identifier cache if we use find_shared_string_identifier(). */ if (type) { f = really_low_find_shared_string_identifier(s, inherit->prog, SEE_PROTECTED); } else { f = find_shared_string_identifier(s, inherit->prog);
1ba3e52001-12-19Martin Stjernholm  }
a5787d1999-03-03Fredrik Hübinette (Hubbe)  if(f<0) {
9606eb2004-11-12Henrik Grubbström (Grubba)  if (s->len < 1024) Pike_error("No such variable (%S) in object.\n", s);
a903032003-02-16Martin Stjernholm  else Pike_error("No such variable in object.\n");
a5787d1999-03-03Fredrik Hübinette (Hubbe)  }else{
a005eb1999-03-04Fredrik Hübinette (Hubbe)  object_low_set_index(o, f+inherit->identifier_level,
a5787d1999-03-03Fredrik Hübinette (Hubbe)  val); pop_n_elems(args); push_int(0); } }
c80f622012-04-29Henrik Grubbström (Grubba) /*! @decl mixed ::_indices(object|void context, int|void access) *! *! @param context *! Context in the current object to start the list from. *! If @expr{UNDEFINED@} or left out, this_program::this *! will be used (ie start at the current context and ignore *! any overloaded symbols). *! *! @param access *! Access permission override. One of the following: *! @int *! @value 0 *! @value UNDEFINED *! See only public symbols. *! @value 1 *! See protected symbols as well. *! @endint
cbe1132001-12-16Martin Stjernholm  *! *! Builtin function to list the identifiers of an object.
e1ea352002-02-14Martin Nilsson  *! This is useful when @[lfun::_indices] has been overloaded.
cbe1132001-12-16Martin Stjernholm  *! *! @seealso
7195af2011-01-15Henrik Grubbström (Grubba)  *! @[::_values()], @[::_types()], @[::`->()]
cbe1132001-12-16Martin Stjernholm  */ static void f_magic_indices (INT32 args) {
c80f622012-04-29Henrik Grubbström (Grubba)  struct object *obj = NULL; struct program *prog = NULL; struct inherit *inherit = NULL;
cbe1132001-12-16Martin Stjernholm  struct array *res;
1ba3e52001-12-19Martin Stjernholm  int type = 0, e, i;
cbe1132001-12-16Martin Stjernholm 
c80f622012-04-29Henrik Grubbström (Grubba)  switch(args) { default: case 2: if (TYPEOF(sp[1-args]) != T_INT) SIMPLE_BAD_ARG_ERROR ("::_indices", 2, "void|int"); type = sp[-args].u.integer; /* FALL THROUGH */
ee3b672011-03-28Henrik Grubbström (Grubba)  case 1:
c80f622012-04-29Henrik Grubbström (Grubba)  if (TYPEOF(sp[-args]) == T_INT) { /* Compat with old-style args. */ type |= (sp[-args].u.integer & 1); if (sp[-args].u.integer & 2) { if(!(obj=MAGIC_THIS->o)) Pike_error("Magic index error\n"); if(!obj->prog) Pike_error("Object is destructed.\n"); inherit = obj->prog->inherits + 0; } } else if (TYPEOF(sp[2-args]) == T_OBJECT) { obj = sp[2-args].u.object; if (obj != MAGIC_THIS->o) Pike_error("::_indices context is not the current object.\n"); if(!obj->prog) Pike_error("::_indices on destructed object.\n"); inherit = obj->prog->inherits + SUBTYPEOF(sp[2-args]);
ee3b672011-03-28Henrik Grubbström (Grubba)  } else {
c80f622012-04-29Henrik Grubbström (Grubba)  SIMPLE_BAD_ARG_ERROR ("::_indices", 1, "void|object|int");
ee3b672011-03-28Henrik Grubbström (Grubba)  }
c80f622012-04-29Henrik Grubbström (Grubba)  /* FALL THROUGH */ case 0:
ee3b672011-03-28Henrik Grubbström (Grubba)  break;
c80f622012-04-29Henrik Grubbström (Grubba)  } if (!obj && !(obj = MAGIC_THIS->o)) Pike_error ("Magic index error\n"); if (!obj->prog) Pike_error ("Object is destructed.\n"); if (!inherit) { /* FIXME: This has somewhat odd behavior if there are local identifiers * before inherits that are overridden by them * (e.g. listing duplicate identifiers). But then again, this is * not the only place where that gives strange effects, imho. * /mast */ inherit = MAGIC_THIS->inherit; } prog = inherit->prog; if (type & 1) { pop_n_elems (args); push_array (res = allocate_array(prog->num_identifier_references)); for (e = i = 0; e < (int) prog->num_identifier_references; e++) { struct reference *ref = prog->identifier_references + e; struct identifier *id = ID_FROM_PTR (prog, ref); if (ref->id_flags & ID_HIDDEN) continue; if ((ref->id_flags & (ID_INHERITED|ID_PRIVATE)) == (ID_INHERITED|ID_PRIVATE)) continue; SET_SVAL(ITEM(res)[i], T_STRING, 0, string, id->name); add_ref(id->name); i++; } res->type_field |= BIT_STRING; sp[-1].u.array = resize_array (res, i); res->type_field = BIT_STRING; return;
1ba3e52001-12-19Martin Stjernholm  }
cbe1132001-12-16Martin Stjernholm 
18942c2001-12-19Martin Stjernholm  pop_n_elems (args);
ee3b672011-03-28Henrik Grubbström (Grubba)  push_array (res = allocate_array_no_init (prog->num_identifier_index, 0)); for (e = 0; e < (int) prog->num_identifier_index; e++) {
017b572011-10-28Henrik Grubbström (Grubba)  SET_SVAL(ITEM(res)[e], T_STRING, 0, string, ID_FROM_INT (prog, prog->identifier_index[e])->name); add_ref(ITEM(res)[e].u.string);
cbe1132001-12-16Martin Stjernholm  }
2523ce2003-04-28Martin Stjernholm  res->type_field = BIT_STRING;
cbe1132001-12-16Martin Stjernholm }
c80f622012-04-29Henrik Grubbström (Grubba) /*! @decl mixed ::_values(object|void context, int|void access) *! *! @param context *! Context in the current object to start the list from. *! If @expr{UNDEFINED@} or left out, this_program::this *! will be used (ie start at the current context and ignore *! any overloaded symbols). *! *! @param access *! Access permission override. One of the following: *! @int *! @value 0 *! @value UNDEFINED *! See only public symbols. *! @value 1 *! See protected symbols as well. *! @endint
cbe1132001-12-16Martin Stjernholm  *! *! Builtin function to list the values of the identifiers of an
e1ea352002-02-14Martin Nilsson  *! object. This is useful when @[lfun::_values] has been overloaded.
cbe1132001-12-16Martin Stjernholm  *! *! @seealso
7195af2011-01-15Henrik Grubbström (Grubba)  *! @[::_indices()], @[::_types()], @[::`->()]
cbe1132001-12-16Martin Stjernholm  */ static void f_magic_values (INT32 args) {
c80f622012-04-29Henrik Grubbström (Grubba)  struct object *obj = NULL; struct program *prog = NULL; struct inherit *inherit = NULL;
cbe1132001-12-16Martin Stjernholm  struct array *res;
2523ce2003-04-28Martin Stjernholm  TYPE_FIELD types;
89ee9e2002-10-28Martin Nilsson  int type = 0, e, i;
cbe1132001-12-16Martin Stjernholm 
c80f622012-04-29Henrik Grubbström (Grubba)  switch(args) { default: case 2: if (TYPEOF(sp[1-args]) != T_INT) SIMPLE_BAD_ARG_ERROR ("::_indices", 2, "void|int"); type = sp[-args].u.integer; /* FALL THROUGH */
ee3b672011-03-28Henrik Grubbström (Grubba)  case 1:
c80f622012-04-29Henrik Grubbström (Grubba)  if (TYPEOF(sp[-args]) == T_INT) { /* Compat with old-style args. */ type |= (sp[-args].u.integer & 1); if (sp[-args].u.integer & 2) { if(!(obj=MAGIC_THIS->o)) Pike_error("Magic index error\n"); if(!obj->prog) Pike_error("Object is destructed.\n"); inherit = obj->prog->inherits + 0; } } else if (TYPEOF(sp[2-args]) == T_OBJECT) { obj = sp[2-args].u.object; if (obj != MAGIC_THIS->o) Pike_error("::_values context is not the current object.\n"); if(!obj->prog) Pike_error("::_values on destructed object.\n"); inherit = obj->prog->inherits + SUBTYPEOF(sp[2-args]);
ee3b672011-03-28Henrik Grubbström (Grubba)  } else {
c80f622012-04-29Henrik Grubbström (Grubba)  SIMPLE_BAD_ARG_ERROR ("::_values", 1, "void|object|int");
ee3b672011-03-28Henrik Grubbström (Grubba)  }
c80f622012-04-29Henrik Grubbström (Grubba)  /* FALL THROUGH */ case 0:
ee3b672011-03-28Henrik Grubbström (Grubba)  break;
c80f622012-04-29Henrik Grubbström (Grubba)  } if (!obj && !(obj = MAGIC_THIS->o)) Pike_error ("Magic index error\n"); if (!obj->prog) Pike_error ("Object is destructed.\n"); if (!inherit) { /* FIXME: This has somewhat odd behavior if there are local identifiers * before inherits that are overridden by them * (e.g. listing duplicate identifiers). But then again, this is * not the only place where that gives strange effects, imho. * /mast */ inherit = MAGIC_THIS->inherit; } prog = inherit->prog; if (type & 1) { pop_n_elems (args); push_array (res = allocate_array(prog->num_identifier_references)); types = 0; for (e = i = 0; e < (int) prog->num_identifier_references; e++) { struct reference *ref = prog->identifier_references + e; struct identifier *id = ID_FROM_PTR (prog, ref); if (ref->id_flags & ID_HIDDEN) continue; if ((ref->id_flags & (ID_INHERITED|ID_PRIVATE)) == (ID_INHERITED|ID_PRIVATE)) continue; low_object_index_no_free (ITEM(res) + i, obj, e + inherit->identifier_level); types |= 1 << TYPEOF(ITEM(res)[i]); i++; } res->type_field |= types; sp[-1].u.array = resize_array (res, i); res->type_field = types; return;
1ba3e52001-12-19Martin Stjernholm  }
cbe1132001-12-16Martin Stjernholm 
18942c2001-12-19Martin Stjernholm  pop_n_elems (args);
ee3b672011-03-28Henrik Grubbström (Grubba)  push_array (res = allocate_array_no_init (prog->num_identifier_index, 0)); types = 0; for (e = 0; e < (int) prog->num_identifier_index; e++) { low_object_index_no_free (ITEM(res) + e, obj, prog->identifier_index[e] + inherit->identifier_level);
017b572011-10-28Henrik Grubbström (Grubba)  types |= 1 << TYPEOF(ITEM(res)[e]);
2523ce2003-04-28Martin Stjernholm  } res->type_field = types;
cbe1132001-12-16Martin Stjernholm }
c80f622012-04-29Henrik Grubbström (Grubba) /*! @decl mixed ::_types(object|void context, int|void access) *! *! @param context *! Context in the current object to start the list from. *! If @expr{UNDEFINED@} or left out, this_program::this *! will be used (ie start at the current context and ignore *! any overloaded symbols). *! *! @param access *! Access permission override. One of the following: *! @int *! @value 0 *! @value UNDEFINED *! See only public symbols. *! @value 1 *! See protected symbols as well. *! @endint
7195af2011-01-15Henrik Grubbström (Grubba)  *! *! Builtin function to list the types of the identifiers of an *! object. This is useful when @[lfun::_types] has been overloaded. *! *! @seealso *! @[::_indices()], @[::_values()], @[::`->()] */ static void f_magic_types (INT32 args) {
c80f622012-04-29Henrik Grubbström (Grubba)  struct object *obj = NULL; struct program *prog = NULL; struct inherit *inherit = NULL;
7195af2011-01-15Henrik Grubbström (Grubba)  struct array *res; TYPE_FIELD types; int type = 0, e, i;
c80f622012-04-29Henrik Grubbström (Grubba)  switch(args) { default: case 2: if (TYPEOF(sp[1-args]) != T_INT) SIMPLE_BAD_ARG_ERROR ("::_types", 2, "void|int"); type = sp[-args].u.integer; /* FALL THROUGH */
ee3b672011-03-28Henrik Grubbström (Grubba)  case 1:
c80f622012-04-29Henrik Grubbström (Grubba)  if (TYPEOF(sp[-args]) == T_INT) { /* Compat with old-style args. */ type |= (sp[-args].u.integer & 1); if (sp[-args].u.integer & 2) { if(!(obj=MAGIC_THIS->o)) Pike_error("Magic index error\n"); if(!obj->prog) Pike_error("Object is destructed.\n"); inherit = obj->prog->inherits + 0; } } else if (TYPEOF(sp[2-args]) == T_OBJECT) { obj = sp[2-args].u.object; if (obj != MAGIC_THIS->o) Pike_error("::_types context is not the current object.\n"); if(!obj->prog) Pike_error("::_types on destructed object.\n"); inherit = obj->prog->inherits + SUBTYPEOF(sp[2-args]);
ee3b672011-03-28Henrik Grubbström (Grubba)  } else {
c80f622012-04-29Henrik Grubbström (Grubba)  SIMPLE_BAD_ARG_ERROR ("::_types", 1, "void|object|int");
ee3b672011-03-28Henrik Grubbström (Grubba)  }
c80f622012-04-29Henrik Grubbström (Grubba)  /* FALL THROUGH */ case 0:
ee3b672011-03-28Henrik Grubbström (Grubba)  break;
c80f622012-04-29Henrik Grubbström (Grubba)  } if (!obj && !(obj = MAGIC_THIS->o)) Pike_error ("Magic index error\n"); if (!obj->prog) Pike_error ("Object is destructed.\n"); if (!inherit) { /* FIXME: This has somewhat odd behavior if there are local identifiers * before inherits that are overridden by them * (e.g. listing duplicate identifiers). But then again, this is * not the only place where that gives strange effects, imho. * /mast */ inherit = MAGIC_THIS->inherit; } prog = inherit->prog; if (type & 1) { pop_n_elems (args); push_array (res = allocate_array(prog->num_identifier_references)); types = 0; for (e = i = 0; e < (int) prog->num_identifier_references; e++) { struct reference *ref = prog->identifier_references + e; struct identifier *id = ID_FROM_PTR (prog, ref); if (ref->id_flags & ID_HIDDEN) continue; if ((ref->id_flags & (ID_INHERITED|ID_PRIVATE)) == (ID_INHERITED|ID_PRIVATE)) continue; SET_SVAL(ITEM(res)[i], PIKE_T_TYPE, 0, type, id->type); add_ref(id->type); i++; types = BIT_TYPE; } res->type_field |= types; sp[-1].u.array = resize_array (res, i); res->type_field = types; return;
7195af2011-01-15Henrik Grubbström (Grubba)  } pop_n_elems (args);
ee3b672011-03-28Henrik Grubbström (Grubba)  push_array (res = allocate_array_no_init (prog->num_identifier_index, 0)); types = 0; for (e = 0; e < (int) prog->num_identifier_index; e++) { struct identifier *id = ID_FROM_INT(prog, prog->identifier_index[e]);
017b572011-10-28Henrik Grubbström (Grubba)  SET_SVAL(ITEM(res)[e], PIKE_T_TYPE, 0, type, id->type); add_ref(id->type);
ee3b672011-03-28Henrik Grubbström (Grubba)  types = BIT_TYPE;
7195af2011-01-15Henrik Grubbström (Grubba)  } res->type_field = types; }
47251d2002-12-11Henrik Grubbström (Grubba) /*! @endnamespace */
15e6012008-04-18Henrik Grubbström (Grubba) void low_init_object(void) { init_destroy_called_mark_hash(); }
a5787d1999-03-03Fredrik Hübinette (Hubbe) void init_object(void) {
080b1a2000-08-10Henrik Grubbström (Grubba)  ptrdiff_t offset;
a5787d1999-03-03Fredrik Hübinette (Hubbe) 
e021fe2008-04-14Henrik Grubbström (Grubba)  enter_compiler(NULL, 0);
c80f622012-04-29Henrik Grubbström (Grubba)  /* ::`->() */
a5787d1999-03-03Fredrik Hübinette (Hubbe)  start_new_program(); offset=ADD_STORAGE(struct magic_index_struct);
95489a2008-06-29Martin Nilsson  MAP_VARIABLE("__obj", tObj, ID_PROTECTED,
892b8a2005-01-20Martin Nilsson  offset + OFFSETOF(magic_index_struct, o), T_OBJECT);
c80f622012-04-29Henrik Grubbström (Grubba)  ADD_FUNCTION("`()", f_magic_index, tFunc(tStr tOr3(tVoid,tObj,tDeprecated(tInt)) tOr(tVoid,tInt), tMix), ID_PROTECTED);
a5787d1999-03-03Fredrik Hübinette (Hubbe)  magic_index_program=end_program();
c80f622012-04-29Henrik Grubbström (Grubba)  /* ::`->=() */
a5787d1999-03-03Fredrik Hübinette (Hubbe)  start_new_program(); offset=ADD_STORAGE(struct magic_index_struct);
95489a2008-06-29Martin Nilsson  MAP_VARIABLE("__obj", tObj, ID_PROTECTED,
892b8a2005-01-20Martin Nilsson  offset + OFFSETOF(magic_index_struct, o), T_OBJECT);
c80f622012-04-29Henrik Grubbström (Grubba)  ADD_FUNCTION("`()", f_magic_set_index, tFunc(tStr tMix tOr3(tVoid,tObj,tDeprecated(tInt)) tOr(tVoid,tInt), tVoid), ID_PROTECTED);
a5787d1999-03-03Fredrik Hübinette (Hubbe)  magic_set_index_program=end_program();
cbe1132001-12-16Martin Stjernholm 
c80f622012-04-29Henrik Grubbström (Grubba)  /* ::_indices() */
cbe1132001-12-16Martin Stjernholm  start_new_program(); offset=ADD_STORAGE(struct magic_index_struct);
95489a2008-06-29Martin Nilsson  MAP_VARIABLE("__obj", tObj, ID_PROTECTED,
892b8a2005-01-20Martin Nilsson  offset + OFFSETOF(magic_index_struct, o), T_OBJECT);
c80f622012-04-29Henrik Grubbström (Grubba)  ADD_FUNCTION("`()", f_magic_indices, tFunc(tOr3(tVoid,tObj,tDeprecated(tInt)) tOr(tVoid,tInt), tArr(tStr)), ID_PROTECTED);
cbe1132001-12-16Martin Stjernholm  magic_indices_program=end_program();
c80f622012-04-29Henrik Grubbström (Grubba)  /* ::_values() */
cbe1132001-12-16Martin Stjernholm  start_new_program(); offset=ADD_STORAGE(struct magic_index_struct);
95489a2008-06-29Martin Nilsson  MAP_VARIABLE("__obj", tObj, ID_PROTECTED,
892b8a2005-01-20Martin Nilsson  offset + OFFSETOF(magic_index_struct, o), T_OBJECT);
c80f622012-04-29Henrik Grubbström (Grubba)  ADD_FUNCTION("`()", f_magic_values, tFunc(tOr3(tVoid,tObj,tDeprecated(tInt)) tOr(tVoid,tInt), tArray), ID_PROTECTED);
cbe1132001-12-16Martin Stjernholm  magic_values_program=end_program();
e021fe2008-04-14Henrik Grubbström (Grubba) 
c80f622012-04-29Henrik Grubbström (Grubba)  /* ::_types() */
7195af2011-01-15Henrik Grubbström (Grubba)  start_new_program(); offset=ADD_STORAGE(struct magic_index_struct); MAP_VARIABLE("__obj", tObj, ID_PROTECTED, offset + OFFSETOF(magic_index_struct, o), T_OBJECT);
c80f622012-04-29Henrik Grubbström (Grubba)  ADD_FUNCTION("`()", f_magic_types, tFunc(tOr3(tVoid,tObj,tDeprecated(tInt)) tOr(tVoid,tInt), tArray), ID_PROTECTED);
7195af2011-01-15Henrik Grubbström (Grubba)  magic_types_program=end_program();
e021fe2008-04-14Henrik Grubbström (Grubba)  exit_compiler();
a5787d1999-03-03Fredrik Hübinette (Hubbe) } void exit_object(void) {
5fa9482001-08-23Henrik Grubbström (Grubba)  if (destruct_object_evaluator_callback) { remove_callback(destruct_object_evaluator_callback); destruct_object_evaluator_callback = NULL; }
7a12332003-07-16Martin Stjernholm  master_is_cleaned_up = 1;
a12b8c2003-03-30Martin Stjernholm  if (master_object) {
7a12332003-07-16Martin Stjernholm  call_destroy (master_object, 1);
09f2882005-02-09Martin Stjernholm  destruct_object (master_object, DESTRUCT_CLEANUP);
a12b8c2003-03-30Martin Stjernholm  free_object(master_object); master_object=0; } if (master_program) { free_program(master_program); master_program=0; } destruct_objects_to_destruct();
a5787d1999-03-03Fredrik Hübinette (Hubbe)  if(magic_index_program) { free_program(magic_index_program); magic_index_program=0; } if(magic_set_index_program) { free_program(magic_set_index_program); magic_set_index_program=0; }
cbe1132001-12-16Martin Stjernholm  if(magic_indices_program) { free_program(magic_indices_program); magic_indices_program=0; } if(magic_values_program) { free_program(magic_values_program); magic_values_program=0; }
7195af2011-01-15Henrik Grubbström (Grubba)  if(magic_types_program) { free_program(magic_types_program); magic_types_program=0; }
a5787d1999-03-03Fredrik Hübinette (Hubbe) }
4647061999-09-14Fredrik Hübinette (Hubbe)  #ifdef PIKE_DEBUG
b040a21999-09-14Fredrik Hübinette (Hubbe) void check_object_context(struct object *o, struct program *context_prog, char *current_storage) { int q;
bad5162000-06-23Fredrik Hübinette (Hubbe)  if(o == Pike_compiler->fake_object) return;
8f29a31999-09-15Fredrik Hübinette (Hubbe)  if( ! o->prog ) return; /* Variables are already freed */
b040a21999-09-14Fredrik Hübinette (Hubbe)  for(q=0;q<(int)context_prog->num_variable_index;q++) { int d=context_prog->variable_index[q];
e0d6f52003-02-13Martin Stjernholm  struct identifier *id = context_prog->identifiers + d;
b040a21999-09-14Fredrik Hübinette (Hubbe)  if(d<0 || d>=context_prog->num_identifiers)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Illegal index in variable_index!\n");
b040a21999-09-14Fredrik Hübinette (Hubbe) 
e0d6f52003-02-13Martin Stjernholm  if(id->run_time_type == T_MIXED)
b040a21999-09-14Fredrik Hübinette (Hubbe)  { struct svalue *s;
e0d6f52003-02-13Martin Stjernholm  s=(struct svalue *)(current_storage + id->func.offset);
b040a21999-09-14Fredrik Hübinette (Hubbe)  check_svalue(s); }else{ union anything *u;
e0d6f52003-02-13Martin Stjernholm  u=(union anything *)(current_storage + id->func.offset);
2e1a6a2008-05-29Henrik Grubbström (Grubba)  if ((id->run_time_type != PIKE_T_GET_SET) && (id->run_time_type != PIKE_T_FREE))
572a912008-03-29Martin Stjernholm  check_short_svalue(u, id->run_time_type);
b040a21999-09-14Fredrik Hübinette (Hubbe)  } } }
4647061999-09-14Fredrik Hübinette (Hubbe) void check_object(struct object *o) { int e; struct program *p; debug_malloc_touch(o);
648a1a2000-06-22Fredrik Hübinette (Hubbe)  debug_malloc_touch(o->storage);
4647061999-09-14Fredrik Hübinette (Hubbe) 
bad5162000-06-23Fredrik Hübinette (Hubbe)  if(o == Pike_compiler->fake_object) return;
5f61da2000-04-13Fredrik Hübinette (Hubbe) 
eff2b02001-07-03Henrik Grubbström (Grubba)  if(o->next)
a4033e2000-04-14Fredrik Hübinette (Hubbe)  {
eff2b02001-07-03Henrik Grubbström (Grubba)  if (o->next == o) { describe(o);
5aad932002-08-15Marcus Comstedt  Pike_fatal("Object check: o->next == o\n");
eff2b02001-07-03Henrik Grubbström (Grubba)  } if (o->next->prev !=o) { describe(o);
5aad932002-08-15Marcus Comstedt  Pike_fatal("Object check: o->next->prev != o\n");
eff2b02001-07-03Henrik Grubbström (Grubba)  }
a4033e2000-04-14Fredrik Hübinette (Hubbe)  }
eff2b02001-07-03Henrik Grubbström (Grubba) 
5f61da2000-04-13Fredrik Hübinette (Hubbe)  if(o->prev) {
eff2b02001-07-03Henrik Grubbström (Grubba)  if (o->prev == o) { describe(o);
5aad932002-08-15Marcus Comstedt  Pike_fatal("Object check: o->prev == o\n");
eff2b02001-07-03Henrik Grubbström (Grubba)  }
5f61da2000-04-13Fredrik Hübinette (Hubbe)  if(o->prev->next != o)
a4033e2000-04-14Fredrik Hübinette (Hubbe)  { describe(o);
5aad932002-08-15Marcus Comstedt  Pike_fatal("Object check: o->prev->next != o\n");
a4033e2000-04-14Fredrik Hübinette (Hubbe)  }
5f61da2000-04-13Fredrik Hübinette (Hubbe)  if(o == first_object)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Object check: o->prev !=0 && first_object == o\n");
5f61da2000-04-13Fredrik Hübinette (Hubbe)  } else { if(first_object != o)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Object check: o->prev ==0 && first_object != o\n");
5f61da2000-04-13Fredrik Hübinette (Hubbe)  } if(o->refs <= 0)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Object refs <= zero.\n");
5f61da2000-04-13Fredrik Hübinette (Hubbe) 
b040a21999-09-14Fredrik Hübinette (Hubbe)  if(!(p=o->prog)) return;
4647061999-09-14Fredrik Hübinette (Hubbe) 
5f61da2000-04-13Fredrik Hübinette (Hubbe)  if(id_to_program(o->prog->id) != o->prog)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Object's program not in program list.\n");
5f61da2000-04-13Fredrik Hübinette (Hubbe) 
e824042001-09-04Fredrik Hübinette (Hubbe)  if(!(o->prog->flags & PROGRAM_PASS_1_DONE)) return;
4647061999-09-14Fredrik Hübinette (Hubbe)  for(e=p->num_inherits-1; e>=0; e--) {
b040a21999-09-14Fredrik Hübinette (Hubbe)  check_object_context(o, p->inherits[e].prog, o->storage + p->inherits[e].storage_offset);
4647061999-09-14Fredrik Hübinette (Hubbe)  } } void check_all_objects(void) { struct object *o, *next; for(o=first_object;o;o=next) { add_ref(o); check_object(o);
69ee4b2000-04-06Fredrik Hübinette (Hubbe)  SET_NEXT_AND_FREE(o,free_object);
4647061999-09-14Fredrik Hübinette (Hubbe)  }
5f61da2000-04-13Fredrik Hübinette (Hubbe)  for(o=objects_to_destruct;o;o=o->next) if(o->refs)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Object to be destructed has references.\n");
4647061999-09-14Fredrik Hübinette (Hubbe) } #endif