예제 #1
0
ENUM_PTRS_END
static RELOC_PTRS_WITH(device_mask_clip_reloc_ptrs, gx_device_mask_clip *mcdev)
{
    RELOC_PREFIX(st_device_forward);
    RELOC_USING(st_gx_strip_bitmap, &mcdev->tiles, sizeof(mcdev->tiles));
    RELOC_USING(st_device_memory, &mcdev->mdev, sizeof(mcdev->mdev));
    if (mcdev->mdev.base != 0) {
	/*
	 * Update the line pointers specially, since they point into the
	 * buffer that is part of the mask clipping device itself.
	 */
	long diff = (char *)RELOC_OBJ(mcdev) - (char *)mcdev;
	int i;

	for (i = 0; i < mcdev->mdev.height; ++i)
	    mcdev->mdev.line_ptrs[i] += diff;
	mcdev->mdev.base = mcdev->mdev.line_ptrs[0];
	mcdev->mdev.line_ptrs =
	    (void *)((char *)(mcdev->mdev.line_ptrs) + diff);
    }
}
예제 #2
0
/* untraced space, so relocate all refs, not just marked ones. */
void
igc_reloc_refs(ref_packed * from, ref_packed * to, gc_state_t * gcst)
{
    int min_trace = gcst->min_collect;
    ref_packed *rp = from;
    bool do_all = gcst->relocating_untraced; 

    vm_spaces spaces = gcst->spaces;
    const gs_memory_t *cmem = space_system->stable_memory;

    while (rp < to) {
	ref *pref;
#ifdef DEBUG
	const void *before = 0;
	const void *after = 0;
# define DO_RELOC(var, stat)\
    BEGIN before = (var); stat; after = (var); END
# define SET_RELOC(var, expr)\
    BEGIN before = (var); after = (var) = (expr); END
#else
# define DO_RELOC(var, stat) stat
# define SET_RELOC(var, expr) var = expr
#endif

	if (r_is_packed(rp)) {
	    rp++;
	    continue;
	}
	/* The following assignment is logically unnecessary; */
	/* we do it only for convenience in debugging. */
	pref = (ref *) rp;
	if_debug3('8', "  [8]relocating %s %d ref at 0x%lx\n",
		  (r_has_attr(pref, l_mark) ? "marked" : "unmarked"),
		  r_btype(pref), (ulong) pref);
	if ((r_has_attr(pref, l_mark) || do_all) &&
	    r_space(pref) >= min_trace
	    ) {
	    switch (r_type(pref)) {
		    /* Struct cases */
		case t_file:
		    DO_RELOC(pref->value.pfile, RELOC_VAR(pref->value.pfile));
		    break;
		case t_device:
		    DO_RELOC(pref->value.pdevice,
			     RELOC_VAR(pref->value.pdevice));
		    break;
		case t_fontID:
		case t_struct:
		case t_astruct:
		    DO_RELOC(pref->value.pstruct,
			     RELOC_VAR(pref->value.pstruct));
		    break;
		    /* Non-trivial non-struct cases */
		case t_dictionary:
		    rputc('d');
		    SET_RELOC(pref->value.pdict,
			      (dict *)igc_reloc_ref_ptr((ref_packed *)pref->value.pdict, gcst));
		    break;
		case t_array:
		    {
			uint size = r_size(pref);

			if (size != 0) {	/* value.refs might be NULL */

			    /*
			     * If the array is large, we allocated it in its
			     * own object (at least originally -- this might
			     * be a pointer to a subarray.)  In this case,
			     * we know it is the only object in its
			     * containing st_refs object, so we know that
			     * the mark containing the relocation appears
			     * just after it.
			     */
			    if (size < max_size_st_refs / sizeof(ref)) {
				rputc('a');
				SET_RELOC(pref->value.refs,
				    (ref *) igc_reloc_ref_ptr(
				     (ref_packed *) pref->value.refs, gcst));
			    } else {
				rputc('A');
				/*
				 * See the t_shortarray case below for why we
				 * decrement size.
				 */
				--size;
				SET_RELOC(pref->value.refs,
				    (ref *) igc_reloc_ref_ptr(
				   (ref_packed *) (pref->value.refs + size),
							       gcst) - size);
			    }
			}
		    }
		    break;
		case t_mixedarray:
		    if (r_size(pref) != 0) {	/* value.refs might be NULL */
			rputc('m');
			SET_RELOC(pref->value.packed,
				  igc_reloc_ref_ptr(pref->value.packed, gcst));
		    }
		    break;
		case t_shortarray:
		    {
			uint size = r_size(pref);

			/*
			 * Since we know that igc_reloc_ref_ptr works by
			 * scanning forward, and we know that all the
			 * elements of this array itself are marked, we can
			 * save some scanning time by relocating the pointer
			 * to the end of the array rather than the
			 * beginning.
			 */
			if (size != 0) {	/* value.refs might be NULL */
			    rputc('s');
			    /*
			     * igc_reloc_ref_ptr has to be able to determine
			     * whether the pointer points into a space that
			     * isn't being collected.  It does this by
			     * checking whether the referent of the pointer
			     * is marked.  For this reason, we have to pass
			     * a pointer to the last real element of the
			     * array, rather than just beyond it.
			     */
			    --size;
			    SET_RELOC(pref->value.packed,
				igc_reloc_ref_ptr(pref->value.packed + size,
						  gcst) - size);
			}
		    }
		    break;
		case t_name:
		    {
			void *psub = name_ref_sub_table(cmem, pref);
			void *rsub = RELOC_OBJ(psub); /* gcst implicit */

			SET_RELOC(pref->value.pname,
				  (name *)
				  ((char *)rsub + ((char *)pref->value.pname -
						   (char *)psub)));
		    } break;
		case t_string:
		    {
			gs_string str;

			str.data = pref->value.bytes;
			str.size = r_size(pref);

			DO_RELOC(str.data, RELOC_STRING_VAR(str));
			pref->value.bytes = str.data;
		    }
		    break;
		case t_oparray:
		    rputc('o');
		    SET_RELOC(pref->value.const_refs,
			(const ref *)igc_reloc_ref_ptr((const ref_packed *)pref->value.const_refs, gcst));
		    break;
		default:
		    goto no_reloc; /* don't print trace message */
	    }
	    if_debug2('8', "  [8]relocated 0x%lx => 0x%lx\n",
		      (ulong)before, (ulong)after);
	}
no_reloc:
	rp += packed_per_ref;
    }
}