Beispiel #1
0
int internal_eqvp(CELL obj1, CELL obj2)
{
	if (AS_LITERAL(obj1) == AS_LITERAL(obj2)) {
		return 1;
	}

	if (! (IS_POINTER(obj1) && IS_POINTER(obj2)) ) {
		return 0;
	}

	TYPEID t = GET_POINTER_TYPE(obj1);
	if (t != GET_POINTER_TYPE(obj2)) {
		return 0;
	}

	switch(t) {
	case T_FLOAT:
		return GET_FLOAT(obj1) == GET_FLOAT(obj2);

	case T_BIGINT:
		return GET_BIGINT(obj1) == GET_BIGINT(obj2);

	default:
		return 0;
	}
	//FIXME - does not implement equality correctly for LAMBDAs
	//principally because LAMBDAs are not implemented correctly
	//yet either (i.e. as closures).
}
Beispiel #2
0
static void   check_ro_ptrpair_sib   (Sib* ap) {
    //        ====================
    //
    Val* p;
    Val* stop;
    Val	 w;

    int gen =  GET_AGE_FROM_SIBID(ap->id);

    if (*sib_is_active(ap))   return;							// sib_is_active	def in    src/c/h/heap.h

    debug_say ("  pairs [%d]: [%#x..%#x:%#x)\n",
	gen, ap->tospace, ap->tospace.first_free, ap->tospace.limit);

    p = ap->tospace + 2;
    stop = ap->tospace.first_free;
    while (p < stop) {
	w = *p++;
	if (IS_TAGWORD(w)) {
	    ERROR;
	    debug_say (
		"** @%#x: unexpected tagword %#x in pair sib\n",
		p-1, w);
	    return;
	}
	else if (IS_POINTER(w)) {
	    check_pointer(p, w, gen, RO_CONSCELL_KIND, CHUNKC_any);
	}
    }
}
Beispiel #3
0
int internal_eqp(CELL obj1, CELL obj2)
{
	if (AS_LITERAL(obj1) == AS_LITERAL(obj2)) {
		return 1;
	}

	if (! (IS_POINTER(obj1) && IS_POINTER(obj2)) ) {
		return 0;
	}

	TYPEID t = GET_POINTER_TYPE(obj1);
	if (t != GET_POINTER_TYPE(obj2)) {
		return 0;
	}

    return 0;
}
Beispiel #4
0
static inline void   forward_to_agegroup1_if_in_agegroup0   (Sibid* book2sibid,  Agegroup* g1,  Val *p, Task* task) {		// 'task' arg is only for debugging, can be dropped in production code.
    //               ====================================
    //
    // Forward *p if it is in agegroup0:

    Val	w =  *p;
    //
    if (IS_POINTER(w)) {
	//
	Sibid  sibid =  SIBID_FOR_POINTER( book2sibid, w );
	//
	if (sibid == AGEGROUP0_SIBID)   *p =  forward_agegroup0_chunk_to_agegroup1( g1, w, task, 0 );
    }
}
Beispiel #5
0
static int
tclOutputFormatGen(char **buf, char *name, DCL_NOM_STR *nom)
{
   int i;

   if (IS_POINTER(nom)) {
      fprintf(stderr, "Pointer %s does not make sense here.\n", name);
      return -1;
   }

   /* List of dimensions */
   bufcat(buf, "{ ");
   for(i=0;i<nom->ndimensions-IS_STRING(nom)?1:0;i++) {
      bufcat(buf, "%d ", nom->dimensions[i]);
   }
   bufcat(buf, "} ");

   if (nom->type->type != STRUCT && nom->type->type != UNION) {
      bufcat(buf, "%s ", name);
   } else {
      /* recurse */
      DCL_NOM_LIST *m;

      bufcat(buf, "{ %s ", name);

      for (m = nom->type->members; m != NULL; m = m->next) {
	 if (m->dcl_nom->name == NULL) { 
	    fprintf(stderr, "Warning: null member name in %s.\n", name);
	    continue;
	 }

	 if (tclOutputFormatGen(buf, m->dcl_nom->name, m->dcl_nom))
	    fprintf(stderr,
		    "Warning: struct member %s was problematic.\n",
		    m->dcl_nom->name);
      }

      bufcat(buf, "} ");
   }
   return 0;
}
Beispiel #6
0
int   get_chunk_age   (Val chunk) {
    //============= 
    // 
    // Get the agegroup of a chunk.
    // Return -1 for external/unboxed chunks.
    //
    // We are called (only) from
    //     src/c/heapcleaner/datastructure-pickler.c	

    if (! IS_POINTER( chunk )) {
	return -1;
    } else {
        //
	Sibid aid =  SIBID_FOR_POINTER( book_to_sibid__global, chunk );
        //
	if (SIBID_KIND_IS_CODE( aid )) {
	    //	

	    int  i;
	    for (i = GET_BOOK_CONTAINING_POINTEE(chunk);  !SIBID_ID_IS_BIGCHUNK_RECORD(aid);  aid = book_to_sibid__global[--i]) {
		continue;
	    }

	    Hugechunk_Quire*
		//
	        hq = (Hugechunk_Quire*) ADDRESS_OF_BOOK( i );

	    Hugechunk*
		//
	        dp =  get_hugechunk_holding_pointee( hq, chunk );

	    return dp->age;

	} else if (aid == AGEGROUP0_SIBID) {	    return  0;
	} else if (BOOK_IS_UNMAPPED(aid)) {	    return -1;
	} else {	 		    	    return  GET_AGE_FROM_SIBID( aid );
	}
    }

}
Beispiel #7
0
int internal_equalp(CELL obj1, CELL obj2)
{
	while(1) {
		if (AS_LITERAL(obj1) == AS_LITERAL(obj2)) {
			return 1;
		}

		if (! (IS_POINTER(obj1) && IS_POINTER(obj2)) ) {
			return 0;
		}

		if (GET_POINTER_TYPE(obj1) != GET_POINTER_TYPE(obj2)) {
			return 0;
		}

		switch(GET_POINTER_TYPE(obj1)) {
		case T_CONS:
            // FIXME - unbounded recursion!
			if (!internal_equalp(CAR(obj1), CAR(obj2))) {
				return 0;
			}
			obj1 = CDR(obj1);
			obj2 = CDR(obj2);
			break;

		case T_VECTOR:
		case T_RECORD:
			{
				VECTOR * const vec1 = GET_VECTOR(obj1);
				VECTOR * const vec2 = GET_VECTOR(obj2);
				if (vec1->len != vec2->len) {
					return 0;
				}
				int i;
				for(i = 0; i < vec1->len; ++i) {
                    // FIXME - unbounded recursion!
					if (!internal_equalp(vec1->data[i], vec2->data[i])) {
						return 0;
					}
				}
				return 1;
			}

		case T_STRING:
			{
				STRING * const p1 = GET_STRING(obj1);
				STRING * const p2 = GET_STRING(obj2);
				return p1->len == p2->len && 0 == memcmp(p1->data, p2->data, p1->len);
			}

        case T_FLOAT:
            return GET_FLOAT(obj1) == GET_FLOAT(obj2);

        case T_BIGINT:
            return GET_BIGINT(obj1) == GET_BIGINT(obj2);

        default:
            return 0;
        }
	}
}
Beispiel #8
0
static void _dump_node_basic(QSP_ARG_DECL  Vec_Expr_Node *enp)
{
	Tree_Code code;
	int i;
	const char *s;

	if( enp==NULL ) return;

	/* print the node "name", and a code that tells about shape knowledge */

// Temporarily print to stderr instead of stdout for debugging...
	prt_node(enp,msg_str);
	prt_msg_frag(msg_str);

	if( SHOWING_LHS_REFS ){
		sprintf(msg_str,"\t%d",VN_LHS_REFS(enp));
		prt_msg_frag(msg_str);
	}

	if( SHOWING_COST ){
		if( VN_SHAPE(enp) != NULL ){
			sprintf(msg_str,"\t%d", SHP_N_MACH_ELTS(VN_SHAPE(enp)));
		}

		prt_msg_frag(msg_str);

		sprintf(msg_str,"\t%d\t%d", VN_FLOPS(enp),VN_N_MATH(enp));
		prt_msg_frag(msg_str);
	}

	if( IS_CURDLED(enp) ){
		sprintf(msg_str,"\t%s (curdled!?)", NNAME(enp));
		prt_msg(msg_str);
		return;
	}

	sprintf(msg_str,"\t%s", NNAME(enp));
	prt_msg_frag(msg_str);

	/* print the special op-dependent args in human-readable form */

	code = VN_CODE(enp);

	if( code==T_DYN_OBJ || code == T_UNDEF || code == T_PROTO || code==T_POINTER || code==T_FUNCPTR || code==T_STR_PTR ){
		sprintf(msg_str,"\t%s",VN_STRING(enp));
		prt_msg_frag(msg_str);
		if( code == T_POINTER ){
			Identifier *idp;
			/* We don't use get_set_ptr() here because we don't want an error msg... */
			idp = id_of(VN_STRING(enp));
			if( idp != NULL && IS_POINTER(idp) && POINTER_IS_SET(idp) ){
				if( PTR_REF(ID_PTR(idp)) == NULL ){
					/* how could this ever happen??? */
					prt_msg_frag("->???");
				} else {
					Data_Obj *dp;
					dp = REF_OBJ(PTR_REF(ID_PTR(idp)));
					sprintf(msg_str,"->%s",OBJ_NAME(dp));
					prt_msg_frag(msg_str);
				}
			}
		}
	} else if( code == T_STATIC_OBJ ){
		sprintf(msg_str,"\t%s",OBJ_NAME(VN_OBJ(enp)));
		prt_msg_frag(msg_str);
#ifdef SCALARS_NOT_OBJECTS
	} else if( code == T_SCALAR_VAR ){
		sprintf(msg_str,"\t%s",VN_STRING(enp));
		prt_msg_frag(msg_str);
#endif // SCALARS_NOT_OBJECTS
	} else if ( code == T_FUNCREF ){
		Subrt *srp;
		srp=VN_SUBRT(enp);
		sprintf(msg_str,"\t%s",SR_NAME(srp));
		prt_msg_frag(msg_str);
	} else if( code == T_SIZE_FN ){
		sprintf(msg_str,"\t%s",FUNC_NAME(VN_FUNC_PTR(enp)));
		prt_msg_frag(msg_str);
	}
#ifdef NOT_YET
	else if(code == T_CALL_NATIVE ){
		// was kw_token???
		// curr_native_func_tbl...
		sprintf(msg_str,"\t%s",FUNC_NAME(VN_FUNC_PTR(enp)));
		prt_msg_frag(msg_str);
	}
#endif /* NOT_YET */
	else if(code == T_TYPECAST ){
		// BUG not how we do precision any more!!!
		//sprintf(msg_str,"  %s",NAME_FOR_PREC_CODE(VN_INTVAL(enp)));
        if( VN_SHAPE(enp) == NULL ) error1("CAUTIOUS:  null node shape for typecast node!?");
        else {
            sprintf(msg_str,"  %s",PREC_NAME(VN_PREC_PTR(enp)));
            prt_msg_frag(msg_str);
        }
    } else if( code == T_SUBRT_DECL || code == T_SCRIPT ){
		Subrt *srp;
		srp=VN_SUBRT(enp);
		sprintf(msg_str,"\t%s",SR_NAME(srp));
		prt_msg_frag(msg_str);
	} else if( code==T_DECL_STAT ){
		//sprintf(msg_str," %s",NAME_FOR_PREC_CODE(VN_INTVAL(enp)));
		sprintf(msg_str," %s",PREC_NAME(VN_DECL_PREC(enp)));
		prt_msg_frag(msg_str);
	} else if( IS_DECL(code) ){
		sprintf(msg_str," %s",VN_STRING(enp));
		prt_msg_frag(msg_str);
	} else if( code==T_ADVISE ){
		/* BUG need to elim yylex_qsp */
		s=eval_string(VN_CHILD(enp,0));
		sprintf(msg_str,"\t\"%s\"",s);
		prt_msg_frag(msg_str);
	} else if( code==T_WARN ){
		/* BUG need to elim yylex_qsp */
		s=eval_string(VN_CHILD(enp,0));
		sprintf(msg_str,"\t\"%s\"",s);
		prt_msg_frag(msg_str);
	} else if( code==T_STRING ){
		sprintf(msg_str,"\t\"%s\"",VN_STRING(enp));
		prt_msg_frag(msg_str);
	} else if( code == T_LABEL || code ==T_GO_BACK || code == T_GO_FWD ){
		sprintf(msg_str," %s",VN_STRING(enp));
		prt_msg_frag(msg_str);
	} else if( code==T_LIT_DBL ){
		sprintf(msg_str," %g",VN_DBLVAL(enp));
		prt_msg_frag(msg_str);
	} else if( code == T_MATH0_FN ){
		sprintf(msg_str," %s",FUNC_NAME(VN_FUNC_PTR(enp)));
		prt_msg_frag(msg_str);
	} else if( code == T_MATH1_FN ){
		sprintf(msg_str," %s",FUNC_NAME(VN_FUNC_PTR(enp)));
		prt_msg_frag(msg_str);
	} else if( code == T_MATH2_FN ){
		sprintf(msg_str," %s",FUNC_NAME(VN_FUNC_PTR(enp)));
		prt_msg_frag(msg_str);
	} else if (
		   code == T_MATH0_VFN
		|| code == T_MATH1_VFN
		|| code == T_MATH2_VFN
		|| code == T_MATH2_VSFN
		|| code == T_CHAR_VFN
			/* BUG? shouldn't there bre a VSFN2 ??? */
		|| code == T_VS_FUNC
		|| code == T_VV_FUNC
		){
		sprintf(msg_str," %s",VF_NAME(FIND_VEC_FUNC(VN_VFUNC_CODE(enp))));
		prt_msg_frag(msg_str);
	} else if( code==T_CALLFUNC ){
assert(VN_SUBRT(enp)!=NULL);
		sprintf(msg_str," %s", SR_NAME(VN_SUBRT(enp)));
		prt_msg_frag(msg_str);
	} else if( code==T_LIT_INT ){
		sprintf(msg_str," %"PRId64, VN_INTVAL(enp) );
		prt_msg_frag(msg_str);
	} else if( code==T_ASSIGN ){
		prt_msg_frag("\t");
	} else if( code==T_MAXVAL ){
		prt_msg_frag("\t");
	} else if( code==T_MINVAL ){
		prt_msg_frag("\t");
	} else if( code==T_RAMP ){
		prt_msg_frag("\t");
	}

	/* Now print the addresses of the child nodes */

	if( VN_CHILD(enp,0)!=NULL){
		sprintf(msg_str,"\t\tn%d",VN_SERIAL(VN_CHILD(enp,0)));
		prt_msg_frag(msg_str);
	}
	for(i=1;i<MAX_CHILDREN(enp);i++){
		if( VN_CHILD(enp,i)!=NULL){
			sprintf(msg_str,", n%d",VN_SERIAL(VN_CHILD(enp,i)));
			prt_msg_frag(msg_str);
		}
	}
	prt_msg("");

	if( SHOWING_SHAPES && VN_SHAPE(enp) != NULL ){
		prt_msg_frag("\t");
		if( OWNS_SHAPE(enp) ){
			sprintf(msg_str,"* 0x%lx  ",(u_long)VN_SHAPE(enp));
			prt_msg_frag(msg_str);
		}
		else {
			sprintf(msg_str,"@ 0x%lx  ",(u_long)VN_SHAPE(enp));
			prt_msg_frag(msg_str);
		}
		prt_msg_frag("\t");
		describe_shape(VN_SHAPE(enp));
	}

	if( SHOWING_RESOLVERS && VN_RESOLVERS(enp)!=NULL ){
		Node *np; Vec_Expr_Node *enp2;
		prt_msg("\tResolvers:");
		np=QLIST_HEAD(VN_RESOLVERS(enp));
		while(np!=NULL){
			enp2=(Vec_Expr_Node *)NODE_DATA(np);
			sprintf(msg_str,"\t\t%s",node_desc(enp2));
			prt_msg(msg_str);
			np=NODE_NEXT(np);
		}
	}
}
Beispiel #9
0
static void   check_ro_pointer_sib   (Sib* ap) {
    //        ====================
    Val* p;
    Val* stop;
    Val  tagword;
    Val  w;
    int	 i;
    int	 len;

    int gen =  GET_AGE_FROM_SIBID( ap->id );

    if (*sib_is_active(ap))   return;							// sib_is_active	def in    src/c/h/heap.h

    debug_say ("  records [%d]: [%#x..%#x:%#x)\n",
	//
        gen,
        ap->tospace,
	ap->tospace.first_free,
	ap->tospace.limit
    );

    p = ap->tospace;
    stop = ap->tospace.first_free;

    while (p < stop) {
	//
	tagword = *p++;

	if (*IS_TAGWORD(tagword)) {
	    ERROR;
	    debug_say (
		"** @%#x: expected tagword, but found %#x in record sib\n",
		p-1, tagword);
	    return;
	}

	switch (GET_BTAG_FROM_TAGWORD tagword) {
	    //
	case PAIRS_AND_RECORDS_BTAG:
	    #
	    len =  GET_LENGTH_IN_WORDS_FROM_TAGWORD( tagword );			// Length excludes tagword.
	    #
	    for (i = 0;  i < len;  i++, p++) {
		w = *p;
		if (IS_TAGWORD(w)) {
		    ERROR;
		    debug_say (
			"** @%#x: unexpected tagword %#x in slot %d of %d\n",
			p, w, i, GET_LENGTH_IN_WORDS_FROM_TAGWORD(tagword));
		    return;
		}
		else if (IS_POINTER(w)) {
		    check_pointer(p, w, gen, RO_POINTERS_KIND, CHUNKC_any);
		}
	    }
	    break;

	case RW_VECTOR_HEADER_BTAG:
	case RO_VECTOR_HEADER_BTAG:
	    //
	    switch (GET_LENGTH_IN_WORDS_FROM_TAGWORD(tagword)) {
		//
	    case TYPEAGNOSTIC_VECTOR_CTAG:
		if (GET_BTAG_FROM_TAGWORD(tagword) == RW_VECTOR_HEADER_BTAG)	check_pointer (p, *p, gen, RO_POINTERS_KIND, CHUNKC__IS_RW_POINTERS);
		else					    			check_pointer (p, *p, gen, RO_POINTERS_KIND, CHUNKC__IS_RO_POINTERS|CHUNKC__IS_RO_CONSCELL);
		break;

	    case VECTOR_OF_ONE_BYTE_UNTS_CTAG:
	    case UNT16_VECTOR_CTAG:
	    case TAGGED_INT_VECTOR_CTAG:
	    case INT1_VECTOR_CTAG:
	    case VECTOR_OF_FOUR_BYTE_FLOATS_CTAG:
	    case VECTOR_OF_EIGHT_BYTE_FLOATS_CTAG:
		check_pointer (p, *p, gen, RO_POINTERS_KIND, CHUNKC__IS_NONPTR_DATA);
		break;

	    default:
		ERROR;
		debug_say ("** @%#x: strange sequence kind %d in record sib\n",
		    p-1, GET_LENGTH_IN_WORDS_FROM_TAGWORD(tagword));
		return;
	    }

	    if (*IS_TAGGED_INT(p[1])) {
		ERROR;
		debug_say ("** @%#x: sequence header length field not an in (%#x)\n",
		    p+1, p[1]);
	    }
	    p += 2;
	    break;

	default:
	    ERROR;
	    debug_say ("** @%#x: strange tag (%#x) in record sib\n",
		p-1, GET_BTAG_FROM_TAGWORD(tagword));
	    return;
	}
    }
}											// fun check_ro_pointer_sib
Beispiel #10
0
static void   check_rw_pointer_sib   (Sib* ap,  Coarse_Inter_Agegroup_Pointers_Map* map)   {		// 'map' is nowhere used in the code?! Should be deleted or used.  XXX BUGGO FIXME
    //        ====================
    //
    Val* p;
    Val* stop;
    Val  tagword;
    Val  w;

    int  i, j;
    int  len;

    int  gen =  GET_AGE_FROM_SIBID(ap->id);

    if (*sib_is_active(ap))   return;							// sib_is_active	def in    src/c/h/heap.h

    debug_say ("  arrays [%d]: [%#x..%#x:%#x)\n",
	//
	gen,
	ap->tospace,
	ap->tospace.first_free,
	ap->tospace.limit
    );

    p = ap->tospace;
    stop = ap->tospace.first_free;

    while (p < stop) {
	tagword = *p++;
	if (*IS_TAGWORD(tagword)) {
	    ERROR;
	    debug_say (
		"** @%#x: expected tagword, but found %#x in vector sib\n",
		p-1, tagword);
	    return;
	}

	switch (GET_BTAG_FROM_TAGWORD(tagword)) {
	    //
	case RW_VECTOR_DATA_BTAG:
	    len = GET_LENGTH_IN_WORDS_FROM_TAGWORD(tagword);
	    break;

	case WEAK_POINTER_OR_SUSPENSION_BTAG:
	    len = 1;
	    break;

	default:
	    ERROR;
	    debug_say ("** @%#x: strange tag (%#x) in vector sib\n",
		p-1, GET_BTAG_FROM_TAGWORD(tagword));
	    return;
	}

	for (int i = 0;  i < len;  i++, p++) {
	    //
	    w = *p;
	    if (IS_TAGWORD(w)) {
		ERROR;
		debug_say (
		    "** @%#x: Unexpected tagword %#x in rw_vector slot %d of %d\n",
		    p, w, i, GET_LENGTH_IN_WORDS_FROM_TAGWORD(tagword));
		for (p -= (i+1), j = 0;  j <= len;  j++, p++) {
		    debug_say ("  %#x: %#10x\n", p, *p);
		}
		return;
	    } else if (IS_POINTER(w)) {
		check_pointer(p, w, gen, RW_POINTERS_KIND, CHUNKC_any);
	    }
	}
    }
}								// fun check_rw_pointer_sib
Beispiel #11
0
static Val   pickle_heap_datastructure   (Task *task,  Val root_chunk,  Pickler_Result* result)   {
    //       =========================
    //
    Heap* heap    =  task->heap;
    int	  max_age =  result->oldest_agegroup_included_in_pickle;

    Vunt  total_sib_buffer_bytesize[ MAX_PLAIN_SIBS ];
    Vunt  total_bytesize;

    struct {
	Vunt		    base;	// Base address of the sib buffer in the heap.
	Vunt		    offset;	// Relative position in the merged sib buffer.
	//
    } adjust[ MAX_AGEGROUPS ][ MAX_PLAIN_SIBS ];

    Sib_Header*  p;										// Sib_Header		def in    src/c/heapcleaner/runtime-heap-image.h
    Sib_Header*  sib_headers[ TOTAL_SIBS ];
    Sib_Header*  sib_header_buffer;

    int  sib_header_bytesize;
    int	 smallchunk_sibs_count;

    Val     pickle;
    Writer* wr;

    // Compute the sib offsets in the heap image:
    //
    for (int ilk = 0;   ilk < MAX_PLAIN_SIBS;   ilk++) {
        //
	total_sib_buffer_bytesize[ ilk ] = 0;
    }

    // The embedded literals go first:
    //
    total_sib_buffer_bytesize[ NONPTR_DATA_SIB ]						// pickler__relocate_embedded_literals	def in   src/c/heapcleaner/datastructure-pickler-cleaner.c
	=
	pickler__relocate_embedded_literals( result, NONPTR_DATA_SIB, 0 );

    // DEBUG debug_say("%d bytes of string literals\n", total_sib_buffer_bytesize[NONPTR_DATA_SIB]);

    for     (int age = 0;  age < max_age;         age++) {
	for (int ilk = 0;  ilk < MAX_PLAIN_SIBS;  ilk++) {
	    //
	    Sib* sib =  heap->agegroup[ age ]->sib[ ilk ];

	    adjust[ age ][ ilk ].offset
		=
		total_sib_buffer_bytesize[ ilk ];

	    if (!sib_is_active(sib)) {								// sib_is_active	def in    src/c/h/heap.h
	        //
		adjust[ age ][ ilk ].base =  0;
		//
	    } else {
		//
		total_sib_buffer_bytesize[ ilk ]
		   +=
		    (Vunt)  sib->tospace.first_free
		    -
		    (Vunt)  sib->tospace.start;

		adjust[ age ][ ilk ].base =  (Vunt) sib->tospace.start;
	    }
	}
    }

    // DEBUG for (ilk = 0;  ilk < MAX_PLAIN_SIBS;  ilk++) debug_say ("sib %d: %d bytes\n", ilk+1, total_sib_buffer_bytesize[ilk]);

    // WHAT ABOUT THE BIG CHUNKS??? XXX BUGGO FIXME

    // Compute the total size of the pickled datastructure:
    //
    smallchunk_sibs_count = 0;
    total_bytesize   = 0;
    //
    for (int ilk = 0;  ilk < MAX_PLAIN_SIBS;  ilk++) {
	//
	if (total_sib_buffer_bytesize[ilk] > 0) {
	    smallchunk_sibs_count++;
	    total_bytesize += total_sib_buffer_bytesize[ilk];
	}
    }

    total_bytesize
       +=
	sizeof( Heapfile_Header )
        +
	sizeof( Pickle_Header    )
	+
	(smallchunk_sibs_count * sizeof( Sib_Header ));

    // COUNT SPACE FOR BIG CHUNKS

    total_bytesize
       +=
	sizeof(Externs_Header)
        +
	heapfile_cfun_table_bytesize( result->cfun_table );    // Include the space for the external symbols (i.e., runtime C functions referenced within the heapgraph).

    // Allocate the heap bytevector for the pickled
    // datastructure representation and initialize
    // the bytevector-writer.
    //
    pickle
	=
	allocate_heap_ram_for_pickle( task, total_bytesize );
    //
    wr =  WR_OpenMem( PTR_CAST(Unt8*, pickle), total_bytesize );							// WR_OpenMem				def in    src/c/heapcleaner/mem-writer.c

    // Initialize the sib headers:
    //
    sib_header_bytesize =  smallchunk_sibs_count * sizeof(Sib_Header);
    //
    sib_header_buffer        =  (Sib_Header*) MALLOC (sib_header_bytesize);
    //
    p = sib_header_buffer;
    //
    for (int ilk = 0;  ilk < MAX_PLAIN_SIBS;  ilk++) {
        //
	if (total_sib_buffer_bytesize[ ilk ] <= 0) {
	    //
	    sib_headers[ilk] = NULL;
	    //
	} else {
	    //
	    p->age		    	    = 0;
	    p->chunk_ilk	    	    = ilk;
	    //
	    p->info.o.base_address	    = 0;   					// Not used.
	    p->info.o.bytesize	    = total_sib_buffer_bytesize[ ilk ];
	    p->info.o.rounded_bytesize = -1;					// Not used.
	    //
	    p->offset		            = -1;  					// Not used.
	    sib_headers[ ilk ]	            = p;
	    p++;
	}
    }

    // What about big chunks? XXX BUGGO FIXME

    // Write the pickle image header:
    //
    if (heapio__write_image_header (wr, NORMAL_DATASTRUCTURE_PICKLE) == FALSE) {								// heapio__write_image_header		def in    src/c/heapcleaner/export-heap-stuff.c
	//
	FREE( sib_header_buffer );

	return PICKLER_ERROR;
    }

    // Write the pickle header:
    //	
    {   Pickle_Header	header;

	header.smallchunk_sibs_count     =  smallchunk_sibs_count;
	header.hugechunk_sibs_count      =  0;			// FIX THIS   XXX BUGGO FIXME
	header.hugechunk_quire_count =  0;			// FIX THIS   XXX BUGGO FIXME

	if (!IS_EXTERNAL_TAG( root_chunk )) {

	    Sibid sibid =  SIBID_FOR_POINTER( book_to_sibid__global, root_chunk );

	    if (!SIBID_KIND_IS_CODE(sibid)) {

		// This is the normal case  --
		// we're saving a vanilla heap value.

		Vunt  addr =  HEAP_POINTER_AS_UNT( root_chunk );

		int age  =  GET_AGE_FROM_SIBID( sibid) - 1;
		int kind =  GET_KIND_FROM_SIBID(sibid) - 1;									// GET_KIND_FROM_SIBID			def in    src/c/h/sibid.h

		addr -= adjust[ age ][ kind ].base;
		addr += adjust[ age ][ kind ].offset;

		header.root_chunk = HIO_TAG_PTR(kind, addr);									// HIO_TAG_PTR				def in    src/c/heapcleaner/runtime-heap-image.h

	    } else {

		//
		Embedded_Chunk_Info*  p
		    =
		    FIND_EMBEDDED_CHUNK( result->embedded_chunk_table, root_chunk );

		if ((p == NULL) || (p->kind == USED_CODE)) {
		    //
		    say_error( "Pickling compiled Mythryl code not implemented\n" );
		    FREE (sib_header_buffer);
		    return PICKLER_ERROR;
		} else {
		    header.root_chunk = p->relocated_address;
		}
	    }

	} else {	// IS_EXTERNAL_TAG( root_chunk )
	    //
	    ASSERT( smallchunk_sibs_count == 0 );

	    header.root_chunk = root_chunk;
	}

	WR_WRITE(wr, &header, sizeof(header));											// WR_WRITE					def in    src/c/heapcleaner/writer.h
	//
	if (WR_ERROR(wr)) {
	    FREE (sib_header_buffer);
	    return PICKLER_ERROR;
	}
    }

    // Record in the pickle the table of heap-referenced
    // runtime C functions.  May also include
    // a handful of assembly fns, exceptions
    // and refcells:
    //
    {   int bytes_written =   heapio__write_cfun_table( wr, result->cfun_table );					// heapio__write_cfun_table			def in    src/c/heapcleaner/export-heap-stuff.c

	if (bytes_written == -1) {
	    FREE( sib_header_buffer );
	    return PICKLER_ERROR;
	}
    }

    // Write the pickle sib headers:
    //
    WR_WRITE (wr, sib_header_buffer, sib_header_bytesize);
    //
    if (WR_ERROR(wr)) {
	FREE (sib_header_buffer);
	return PICKLER_ERROR;
    }

    // Write the pickled datastructure proper:
    //
    for (int ilk = 0;  ilk < MAX_PLAIN_SIBS;  ilk++) {
	//
	if (ilk == NONPTR_DATA_SIB) {

	    // Write into the pickle the required embedded literals:
            //
	    pickler__pickle_embedded_literals( wr );										// pickler__pickle_embedded_literals		def in    src/c/heapcleaner/datastructure-pickler-cleaner.c

	    // Write into the pickle remaining required strings:
            //
	    for (int age = 0;  age < max_age;  age++) {
		//
		Sib* sib = heap->agegroup[ age ]->sib[ ilk ];

		if (sib_is_active(sib)) {											// sib_is_active				def in    src/c/h/heap.h
		    //
		    WR_WRITE(
                        wr,
                        sib->tospace.start,
			(Vunt) sib->tospace.first_free
                       -(Vunt) sib->tospace.start
                    );
		}
	    }

	} else {

	    for (int age = 0;  age < max_age;  age++) {
		//
		Sib* sib = heap->agegroup[ age ]->sib[ ilk ];

		if (sib_is_active( sib )) {
		    //
		    Val*  top =  sib->tospace.first_free;
		    //
		    for (Val*
			p =  sib->tospace.start;
                        p <  top;
                        p++
		    ){
			Val w =  *p;

			if (IS_POINTER(w)) {
			    //
			    Sibid sibid =  SIBID_FOR_POINTER( book_to_sibid__global, w );

			    if (BOOK_IS_UNMAPPED(sibid)) {
				//
				w =  add_cfun_to_heapfile_cfun_table( result->cfun_table, w);

				ASSERT (w != HEAP_VOID);

			    } else if (SIBID_KIND_IS_CODE(sibid)) {

				Embedded_Chunk_Info*  chunk_info
				    =
				    FIND_EMBEDDED_CHUNK( result->embedded_chunk_table, w );

				if (chunk_info == NULL
				||  chunk_info->kind == USED_CODE
				){
				    die("Pickling of Mythryl compiled code not implemented");
				} else {
				    w = chunk_info->relocated_address;
                                }

			    } else {

			        // Adjust the pointer:
                                //
				int  age  =  GET_AGE_FROM_SIBID( sibid)-1;
				int  kind =  GET_KIND_FROM_SIBID(sibid)-1;

				Vunt addr =  HEAP_POINTER_AS_UNT(w);

				addr -=  adjust[ age ][ kind ].base;
				addr +=  adjust[ age ][ kind ].offset;

				w = HIO_TAG_PTR( kind, addr );
			    }
			}								// if (IS_POINTER(w))
			WR_PUT(wr, (Vunt)w);
		    }									// for
		}
	    }
	}
    }

    FREE( sib_header_buffer );

    if (WR_ERROR(wr))	return PICKLER_ERROR;

    return  make_vector_header(task, STRING_TAGWORD, pickle, total_bytesize);
}											// fun pickle_heap_datastructure
Beispiel #12
0
static int
tclInputFormatGen(char **buf, char *name, DCL_NOM_STR *nom,
		  RQST_INPUT_INFO_LIST **iinfo, int level)
{
   char *arrayName = NULL;	/* in the case of an array */
   static char defaultDefault[20];

   if (IS_POINTER(nom)) {
      fprintf(stderr, "Pointer %s does not make sense here.\n", name);
      return -1;
   }

   /* For an array, must do some loop */
   if (IS_ARRAY(nom)) {
      int i;

      bufcat(&arrayName, name);

      for(i=0;i<nom->ndimensions-IS_STRING(nom)?1:0;i++) {
	 bufcat(buf,"    for {set loop%d(%d) 0} "
		"{ \\$loop%d(%d)<%d } { incr loop%d(%d)} {\n",
		level, i, level, i, nom->dimensions[i], level, i);
	 bufcat(&arrayName, "\\\\[\\$loop%d(%d)\\\\]", level, i);
      }

      if (arrayName == NULL) {
	 /* must give up */
	 fprintf(stderr, "Warning: could not generate array name for %s.\n",
		 name);
	 return -1;
      }

      name = arrayName;
   }

   if (nom->type->type != STRUCT && nom->type->type != UNION) {

      bufcat(buf, "    lappend format [list ");

      /* Echo the tcl func call */
      switch (nom->type->type) {

	 case CHAR:
	    if (IS_STRING(nom))
	       bufcat(buf, "string");
	    else
	       bufcat(buf, "short");
	    strcpy(defaultDefault, "\"\"");
	    break;
	 
	 case SHORT:
	    bufcat(buf, "short");
	    strcpy(defaultDefault, "0");
	    break;

	 case INT:
	    if (nom->type->flags & LONG_LONG_INT)
	       bufcat(buf, "wide");
	    else 
	       bufcat(buf, "int");
	    strcpy(defaultDefault, "0");
	    break;
		
	 case FLOAT:
	    bufcat(buf, "float");
	    strcpy(defaultDefault, "0.0");
	    break;

	 case DOUBLE:
	    bufcat(buf, "double");
	    strcpy(defaultDefault, "0.0");
	    break;
	 
	 case STRUCT:
	 case UNION:
	    /* see 'else' statement below */
	    break;

	    /* Affichage en clair des symboles de l'enum */
	 case ENUM:
	    bufcat(buf, "{ ");
	    if (tclGenEnumList(buf, nom->type) != 0)
	       return -1;
	    bufcat(buf, "}");
	    strcpy(defaultDefault, "\"\"");
	    break;

	 case TYPEDEF:
	    fprintf(stderr, "Warning: encountered a typedef for %s.\n", name);
	    break;
      }

      if (*iinfo != NULL && (*iinfo)->doc != NULL) {
	 bufcat(buf, " \"%s\"", (*iinfo)->doc);
	 switch((*iinfo)->type) {
	    case INT:
	       if (nom->type->type == ENUM) {
		  int ok = 0;
		  DCL_NOM_LIST *member;

		  for(member = nom->type->members;
		      member != NULL;
		      member = member->next) {
		     if (member->dcl_nom->pointeur ==
			 (*iinfo)->default_val.i_val) {
			bufcat(buf, " \"%s\"", member->dcl_nom->name);
			ok = 1;
			break;
		     }
		  }
		  if (!ok)
		     bufcat(buf, " %d", (*iinfo)->default_val.i_val);

	       } else
		  bufcat(buf, " %d", (*iinfo)->default_val.i_val);
	       break;
	    case DOUBLE:
	       bufcat(buf, " %f", (*iinfo)->default_val.d_val);
	       break;
	    case CHAR:
	       bufcat(buf, " \"%s\"", (*iinfo)->default_val.str_val);
	       break;
	 }
      }
      else
	 bufcat(buf, " \"%s\" %s", name, defaultDefault);

      bufcat(buf, " ]\n");

   } else { /* STRUCT || UNION */
      /* recurse */
      DCL_NOM_LIST *m;
      char *var;

      for (m = nom->type->members; m != NULL; m = m->next) {
	 var = NULL;

	 bufcat(&var, "%s.%s", name, m->dcl_nom->name);
	 if (var == NULL) { 
	    fprintf(stderr, "Warning: null member name in %s.\n", name);
	    continue;
	 }

	 if (tclInputFormatGen(buf, var, m->dcl_nom, iinfo, level+1))
	    fprintf(stderr, "Warning: struct member %s was problematic.\n",
		    var);

	 free(var);
      }
   }
	  
   if (IS_ARRAY(nom)) {
      int i;

      /* End array scanning */
      for(i=IS_STRING(nom)?1:0;i<nom->ndimensions;i++) {
	 bufcat(buf, "}\n");
      }
      free(arrayName);
   }

   if (nom->type->type != STRUCT && nom->type->type != UNION)
      if ((*iinfo) != NULL) *iinfo = (*iinfo)->next;
   return 0;
}
Beispiel #13
0
static Val   forward_special_chunk   (Agegroup* ag1,  Val* chunk,   Val tagword)   {
    //       =====================
    // 
    // Forward a special chunk (suspension or weak pointer).

    Sib*  sib =  ag1->sib[ RW_POINTERS_SIB ];						// Special chunks can be updated (modified)
											// so they have to go in RW_POINTERS_SIB.
    Val*  new_chunk = sib->tospace.first_free;

    sib->tospace.first_free += SPECIAL_CHUNK_SIZE_IN_WORDS;			// All specials are two words.

    switch (GET_LENGTH_IN_WORDS_FROM_TAGWORD( tagword )) {
        //
    case EVALUATED_LAZY_SUSPENSION_CTAG:
    case UNEVALUATED_LAZY_SUSPENSION_CTAG:
        //
	*new_chunk++ = tagword;
	*new_chunk = *chunk;
	break;

    case WEAK_POINTER_CTAG:
        {
      	    //
	    Val	v = *chunk;
									    #ifdef DEBUG_WEAKREFS
										debug_say ("MinorGC: weak [%#x ==> %#x] --> %#x", chunk, new_chunk+1, v);
									    #endif

	    if (! IS_POINTER( v )) {
										#ifdef DEBUG_WEAKREFS
										debug_say (" unboxed\n");
										#endif

	        // Weak references to unboxed chunks (i.e., immediate Int31)
		// can never be nullified, since Int31 values, being stored
		// in-pointer, take no actual heapspace and thus cannot actually
		// ever get garbage-collected.  Consequently, we can just copy
		// such weakrefs over and skip the rest of our usual processing:
                //
		new_chunk[0] = WEAKREF_TAGWORD;
		new_chunk[1] = v;

		++new_chunk;

	    } else {

		Sibid sibid =  SIBID_FOR_POINTER( book_to_sibid__global, v );
		Val*  vp    =  PTR_CAST( Val*, v );

		if (sibid != AGEGROUP0_SIBID) {

		    // Weakref points to a value in an older heap agegroup.
		    // Since we are only heapcleaning agegroup0 in
		    // this file, the referenced value cannot get
		    // garbage-collected this pass, so we can skip
		    // the usual work to check for that and if necessary
		    // null out the weakref:
		    //
										    #ifdef DEBUG_WEAKREFS
											debug_say (" old chunk\n");
										    #endif

		    new_chunk[0] =  WEAKREF_TAGWORD;
		    new_chunk[1] =  v;

		    ++new_chunk;

		} else {

		    //
		    if (vp[-1] == FORWARDED_CHUNK_TAGWORD) {
		        //
			// Reference to a chunk that has already been forwarded.
			// Note that we have to put the pointer to the non-forwarded
			// copy of the chunk (i.e, v) into the to-space copy
			// of the weak pointer, since the heapcleaner has the invariant
			// that it never sees to-space pointers during sweeping.
											#ifdef DEBUG_WEAKREFS
											    debug_say (" already forwarded to %#x\n", PTR_CAST( Val, FOLLOW_FORWARDING_POINTER(vp)));
											#endif

			new_chunk[0] =  WEAKREF_TAGWORD;
			new_chunk[1] =  v;

			++new_chunk;

		    } else {

			// This is the important case: We are copying a weakref
			// of an agegroup0 value.  That agegroup0 value might get
			// get garbage-collected this pass; if it does, we must null
			// out the weakref.
			//
			// To do this efficiently, as we copy such weakrefs from
			// agegroup0 into agegroup1 we chain them togther via
			// their tagword fields with the root pointer kept
                        // in ag1->heap->weakrefs_forwarded_during_heapcleaning.
			//
			// At the end of heapcleaning we will consume this chain of
			// weakrefs in null_out_newly_dead_weakrefs() where					// null_out_newly_dead_weakrefs	is from   src/c/heapcleaner/heapcleaner-stuff.c
			// we will null out any newly dead weakrefs and then
			// replace the chainlinks with valid tagwords -- either
			// WEAKREF_TAGWORD or NULLED_WEAKREF_TAGWORD,
			// as appropriate, thus erasing our weakref chain and
			// restoring sanity.
			//
                        // We mark the chunk reference field in the forwarded copy
			// to make it look like an Tagged_Int so that the to-space
			// sweeper does not follow the weak reference.
											#ifdef DEBUG_WEAKREFS
											    debug_say (" forward\n");
											#endif

			new_chunk[0] =  MARK_POINTER(PTR_CAST( Val, ag1->heap->weakrefs_forwarded_during_heapcleaning ));		// MARK_POINTER just sets the low bit to 1, making it look like an Int31 value
			new_chunk[1] =  MARK_POINTER( vp );										// MARK_POINTER		is from   src/c/h/heap-tags.h

			ag1->heap->weakrefs_forwarded_during_heapcleaning =  new_chunk;

			++new_chunk;
		    }
		}
	    }
	}
	break;

    case NULLED_WEAK_POINTER_CTAG:					// Shouldn't happen in agegroup0.
    default:
	die (
            "strange/unexpected special chunk @ %#x; tagword = %#x\n",
            chunk, tagword
	);
    }								// switch (GET_LENGTH_IN_WORDS_FROM_TAGWORD(tagword))

    chunk[-1] =  FORWARDED_CHUNK_TAGWORD;
    chunk[ 0] =  (Val) (Vunt) new_chunk;

    return   PTR_CAST( Val, new_chunk );
}								// fun forward_special_chunk
Beispiel #14
0
static void   process_task_heap_changelog   (Task* task, Heap* heap) {
    //        ===========================
    // 
    // As tasks run, they note all stores into pointer-valued					// Tagged-Int-valued refcells cannot contain cross-generation pointers so we don't track them in changelog.
    // refcells and rw_vectors in the 'heap_changelog',
    // a lisp-style list of "CONS cells" -- (val,next) pointer-pairs.
    // 
    // We need this done because such stores into the heap
    // can introduce pointers from one agegroup into a
    // younger agegroup, which we need to take into account
    // when doing partial heapcleanings ("garbage collections").
    //
    // Our job here is to promote to agegroup 1 all agegroup0
    // values referenced by a refcell/vectorslot in the heap_changelog.

    Val this_heap_changelog_cell =  task->heap_changelog; 
    if (this_heap_changelog_cell == HEAP_CHANGELOG_NIL)   return;				// Abort quickly if no work to do.

    int updates        = 0;									// Heapcleaner statistics.
    Agegroup* age1     =  heap->agegroup[ 0 ];							// Cache heap entry for speed.
    Sibid* b2s         =  book_to_sibid__global;						// Cache global locally for speed.   book_to_sibid__global	def in    src/c/heapcleaner/heapcleaner-initialization.c

    while (this_heap_changelog_cell != HEAP_CHANGELOG_NIL) {					// Over all entries in the heap_changelog.
	//
	++updates;										// Heapcleaner statistics.

	Val* pointer   	         =  HEAP_CHANGELOG_HEAD( this_heap_changelog_cell );		// Get pointer to next updated refcell/vector slot to process.
	this_heap_changelog_cell =  HEAP_CHANGELOG_TAIL( this_heap_changelog_cell );		// Step to next cell in heap_changelog list.

	Val pointee = *pointer;									// Get contents of updated refcell/vectorslot.

	if (!IS_POINTER( pointee ))   continue;							// Ignore refcells and vectorslots containing Tagged_Int values.

	Sibid src_sibid =  SIBID_FOR_POINTER(b2s, pointer );					// Get the Sibid tag for the ram-book containing the refcell/vectorslot.	Sibid  def in    src/c/h/sibid.h

	if (src_sibid == AGEGROUP0_SIBID)    continue;						// Ignore updates to agegroup0      refcells and vectorslots.
	if (BOOK_IS_UNMAPPED( src_sibid ))   continue;						// Ignore updates to runtime-global refcells and vectorslots, which are handled elsewhere.

	Sibid dst_sibid =  SIBID_FOR_POINTER(b2s, pointee );					// Get the Sibid tag for the ram-book containing the value referenced by the refcell/vectorslot.
	//
	int src_age =  GET_AGE_FROM_SIBID( src_sibid );						// agegroup of the updated refcell/vectorslot.
	int dst_age =  GET_AGE_FROM_SIBID( dst_sibid );						// agegroup of the chunk that the refcell/vectorslot points to.

	if (!SIBID_KIND_IS_CODE( dst_sibid )) {
	    //
	    if (dst_age == AGEGROUP0) {
		//
		*pointer =  forward_agegroup0_chunk_to_agegroup1( age1, pointee,task, 1);	// Promote pointee to agegroup 1.
		dst_age = 1;									// Remember pointee now has age 1, not 0.
		//
	    }

	} else {										// Refcell/vector slot is pointing to code.	

	    if (dst_age >= src_age)   continue;

            dst_age =  get_age_of_codechunk( pointee );
	}

	// Maybe update min_age value for
	// the card containing 'pointer':
	//
	if (src_age > dst_age) {
	    //
	    MAYBE_UPDATE_CARD_MIN_AGE_PER_POINTER(						// MAYBE_UPDATE_CARD_MIN_AGE_PER_POINTER	def in    src/c/h/coarse-inter-agegroup-pointers-map.h
		//
		heap->agegroup[ src_age-1 ]->coarse_inter_agegroup_pointers_map,
		pointer,
		dst_age
	    );
	}
    }

    update_count__global += updates;								// Cleaner statistics.  Apparently never used.

    task->heap_changelog =  HEAP_CHANGELOG_NIL;							// We're done with heap_changelog so clear it.

}												// fun process_task_heap_changelog