static bool write_ref( sbuffer *b, value o, value *serialize ) { odatalist *d = b->refs, *prev = NULL; while( d != NULL ) { if( d->data < o ) { prev = d; d = d->left; } else if( d->data == o ) { write_char(b,'r'); write_int(b,b->nrefs - 1 - d->k); return true; } else { prev = d; d = d->right; } } if( serialize != NULL ) { *serialize = NULL; val_iter_fields(o,lookup_serialize_field,serialize); if( *serialize != NULL ) return false; } d = (odatalist*)alloc(sizeof(odatalist)); d->data = o; d->k = b->nrefs++; d->left = NULL; d->right = NULL; if( prev == NULL ) b->refs = d; else if( prev->data < o ) prev->left = d; else prev->right = d; return false; }
static value dump_prof() { dump_param p; value o = val_this(); value cache; val_check(o,object); cache = val_field(o,id_cache); val_check(cache,object); p.tot = 0; p.callb = profile_total; val_iter_fields(cache,dump_module,&p); printf("Summary :\n"); p.callb = profile_summary; val_iter_fields(cache,dump_module,&p); printf("%10d\n\n",p.tot); printf("Functions :\n"); p.callb = profile_functions; val_iter_fields(cache,dump_module,&p); printf("\n"); p.callb = profile_details; val_iter_fields(cache,dump_module,&p); return val_true; }
static void val_buffer_rec( buffer b, value v, vlist *stack ) { char buf[32]; int i, l; vlist *vtmp = stack; while( vtmp != NULL ) { if( vtmp->v == v ) { buffer_append_sub(b,"...",3); return; } vtmp = vtmp->next; } switch( val_type(v) ) { case VAL_INT: buffer_append_sub(b,buf,sprintf(buf,"%d",val_int(v))); break; case VAL_STRING: buffer_append_sub(b,val_string(v),val_strlen(v)); break; case VAL_FLOAT: buffer_append_sub(b,buf,sprintf(buf,FLOAT_FMT,val_float(v))); break; case VAL_NULL: buffer_append_sub(b,"null",4); break; case VAL_BOOL: if( val_bool(v) ) buffer_append_sub(b,"true",4); else buffer_append_sub(b,"false",5); break; case VAL_FUNCTION: buffer_append_sub(b,buf,sprintf(buf,"#function:%d",val_fun_nargs(v))); break; case VAL_OBJECT: { value s = val_field(v,id_string); if( s != val_null ) s = val_callEx(v,s,NULL,0,NULL); if( val_is_string(s) ) buffer_append_sub(b,val_string(s),val_strlen(s)); else { vlist2 vtmp; vtmp.v = v; vtmp.next = stack; vtmp.b = b; vtmp.prev = 0; buffer_append_sub(b,"{",1); val_iter_fields(v,val_buffer_fields,&vtmp); if( vtmp.prev ) buffer_append_sub(b," }",2); else buffer_append_sub(b,"}",1); } break; } case VAL_ARRAY: buffer_append_sub(b,"[",1); l = val_array_size(v); { vlist vtmp; vtmp.v = v; vtmp.next = stack; for(i=0;i<l;i++) { value vi = val_array_ptr(v)[i]; val_buffer_rec(b,vi,&vtmp); if( i != l - 1 ) buffer_append_sub(b,",",1); } } buffer_append_sub(b,"]",1); break; case VAL_INT32: buffer_append_sub(b,buf,sprintf(buf,"%d",val_int32(v))); break; case VAL_ABSTRACT: buffer_append_sub(b,"#abstract",9); break; default: buffer_append_sub(b,"#unknown",8); break; } }
static void hash_rec( value v, int *h, vlist *l ) { val_type t = val_type(v); switch( t ) { case VAL_INT: HBIG(val_int(v)); break; case VAL_INT32: HBIG(val_int32(v)); break; case VAL_NULL: HSMALL(0); break; case VAL_FLOAT: { int k = sizeof(tfloat); while( k ) HSMALL(val_string(v)[--k]); } break; case VAL_BOOL: HSMALL(val_bool(v)); break; case VAL_STRING: { int k = val_strlen(v); while( k ) HSMALL(val_string(v)[--k]); } break; case VAL_OBJECT: case VAL_ARRAY: { vlist *tmp = l; int k = 0; while( tmp != NULL ) { if( tmp->v == v ) { HSMALL(k); return; } k = k + 1; tmp = tmp->next; } } if( t == VAL_OBJECT ) { vparam p; p.h = h; p.l.v = v; p.l.next = l; val_iter_fields(v,hash_obj_rec,&p); v = (value)((vobject*)v)->proto; if( v != NULL ) hash_rec(v,h,&p.l); } else { vlist cur; int k = val_array_size(v); cur.v = v; cur.next = l; while( k ) hash_rec(val_array_ptr(v)[--k],h,&cur); } break; default: // ignore since we want hashes to be stable wrt memory break; } }
void serialize_rec( sbuffer *b, value o ) { b->nrec++; if( b->nrec > 350 ) failure("Serialization stack overflow"); switch( val_type(o) ) { case VAL_NULL: write_char(b,'N'); break; case VAL_BOOL: if( val_bool(o) ) write_char(b,'T'); else write_char(b,'F'); break; case VAL_INT: write_char(b,'i'); write_int(b,val_int(o)); break; case VAL_FLOAT: write_char(b,'f'); write_str(b,sizeof(tfloat),&val_float(o)); break; case VAL_STRING: if( !write_ref(b,o,NULL) ) { write_char(b,'s'); write_int(b,val_strlen(o)); write_str(b,val_strlen(o),val_string(o)); } break; case VAL_OBJECT: { value s; if( !write_ref(b,o,&s) ) { if( s != NULL ) { // reference was not written if( !val_is_function(s) || (val_fun_nargs(s) != 0 && val_fun_nargs(s) != VAR_ARGS) ) failure("Invalid __serialize method"); write_char(b,'x'); serialize_rec(b,((neko_module*)((vfunction*)s)->module)->name); serialize_rec(b,val_ocall0(o,id_serialize)); // put reference back write_ref(b,o,NULL); break; } write_char(b,'o'); val_iter_fields(o,serialize_fields_rec,b); write_int(b,0); o = (value)((vobject*)o)->proto; if( o == NULL ) write_char(b,'z'); else { write_char(b,'p'); serialize_rec(b,o); } } } break; case VAL_ARRAY: if( !write_ref(b,o,NULL) ) { int i; int n = val_array_size(o); write_char(b,'a'); write_int(b,n); for(i=0;i<n;i++) serialize_rec(b,val_array_ptr(o)[i]); } break; case VAL_FUNCTION: if( !write_ref(b,o,NULL) ) { neko_module *m; if( val_tag(o) == VAL_PRIMITIVE ) { // assume that alloc_array(0) return a constant array ptr // we don't want to access custom memory (maybe not a ptr) if( ((vfunction*)o)->env != alloc_array(0) ) failure("Cannot Serialize Primitive with environment"); write_char(b,'p'); write_int(b,((vfunction*)o)->nargs); serialize_rec(b,((vfunction*)o)->module); break; } if( val_tag(o) == VAL_JITFUN ) failure("Cannot Serialize JIT method"); write_char(b,'L'); m = (neko_module*)((vfunction*)o)->module; serialize_rec(b,m->name); write_int(b,(int)((int_val*)((vfunction*)o)->addr - m->code)); write_int(b,((vfunction*)o)->nargs); serialize_rec(b,((vfunction*)o)->env); } break; case VAL_INT32: write_char(b,'I'); write_int(b,val_int32(o)); break; case VAL_ABSTRACT: if( val_is_kind(o,k_hash) ) { int i; vhash *h = val_hdata(o); write_char(b,'h'); write_int(b,h->ncells); write_int(b,h->nitems); for(i=0;i<h->ncells;i++) { hcell *c = h->cells[i]; while( c != NULL ) { write_int(b,c->hkey); serialize_rec(b,c->key); serialize_rec(b,c->val); c = c->next; } } break; } default: failure("Cannot Serialize Abstract"); break; } b->nrec--; }
void api_val_iter_fields(value inObj, __hx_field_iter inFunc ,void *inCookie) { val_iter_fields(inObj,inFunc,inCookie); }