Exemple #1
0
rt_public EIF_BOOLEAN eequal(register EIF_REFERENCE target, register EIF_REFERENCE source)
{
	/* Eiffel standard equality: it assumes that dynamic type of Eiffel
	 * object refered by `source' conforms to dynamic type of Eiffel
	 * object refered by `target'. `source' and `target' cannot be NULL
	 * or special objects here.
	 * If both `source' and `target' have the same dynamic type and this
	 * type is not composite, then perform a block comparison; otherwise
	 * perform a field by field comparison.
	 * It is the feature `standard_is_equal' of class ANY.
	 * Return a boolean.
	 */

	REQUIRE ("source_not_null", source);
	REQUIRE ("target_not_null", target);

	if (source == target) {
			/* Minor optimization, if references are equal then it is the same object. */
		return EIF_TRUE;
	}

	if (Dftype(source) == Dftype(target)) {
		/* Dynamic type are the same: because of the intra-expanded
		 * references, we can perform only a block comparison if
		 * the target (or the source) is a composite object (i.e: it has
		 * expanded attributes): since an attribute keeps expanded or
		 * not expanded all the time, we can test either the source or
		 * the target.
		 */
		if (HEADER(source)->ov_flags & EO_SPEC) {
				/* Works for both SPECIAL and TUPLE object */
				/* Eiffel standard equality on special objects: type check assumes
				* the comparison is on areas of the same type (containing the same
				* thing). Called by the redefinition of feature `equal' of special
				* class. `source' and/or `target' cannot be NULL.
				* Return a boolean.
				*/

				/* First condition: same count */
			if
				((RT_SPECIAL_COUNT(source) != RT_SPECIAL_COUNT(target)) ||
				(RT_SPECIAL_ELEM_SIZE(source) != RT_SPECIAL_ELEM_SIZE(target)))
			{
				return EIF_FALSE;
			} else {
					/* Second condition: block equality */
				return EIF_TEST(!memcmp (source, target, RT_SPECIAL_VISIBLE_SIZE(source)));
			}
		} else {
			if (!(HEADER(source)->ov_flags & EO_COMP))	/* Perform a block comparison */
				return EIF_TEST(!memcmp (source, target, EIF_Size(Dtype(source))));
			else
				return e_field_equal(target, source);
		}
	}

	/* Field by field comparison */

	return EIF_FALSE;
}
Exemple #2
0
rt_public void eif_std_ref_copy(register EIF_REFERENCE source, register EIF_REFERENCE target)
{
    /* Copy Eiffel object `source' into Eiffel object `target'.
     * Dynamic type of `source' is supposed to be the same as dynamic type
     * of `target'. It assumes also that `source' and `target' are not
     * references on special objects.
     * Problem: updating intra-references on expanded object
     * because the garbage collector needs to explore those references.
     */

    uint16 flags;			/* Source object flags */
    union overhead *s_zone;	/* Source object header */
    union overhead *t_zone;	/* Target object header */
#ifdef ISE_GC
    EIF_REFERENCE enclosing;					/* Enclosing target object */
#endif
    rt_uint_ptr size;

    s_zone = HEADER(source);
    flags = s_zone->ov_flags;
    t_zone = HEADER(target);

    if (s_zone->ov_dftype == t_zone->ov_dftype) {

        if (flags & EO_COMP) {
            /* Case of composite object: updating of references on expanded objects. */
            eif_std_field_copy (source, target);
        } else {
            /* Copy of source object into target object with same dynamic type. Block copy here. */
            if (flags & EO_SPEC) {
                size = RT_SPECIAL_VISIBLE_SIZE(source);
            } else {
                size = EIF_Size(s_zone->ov_dtype);
            }
            memmove(target, source, size);
        }

#ifdef ISE_GC
        /* Precompute the enclosing target object */
        enclosing = target;					/* By default */
        if (eif_is_nested_expanded(t_zone->ov_flags)) {
            enclosing -= t_zone->ov_size & B_SIZE;
        }

        /* Perform aging tests. We need the address of the enclosing object to
         * update the flags there, in case the target is to be memorized.
         */
        flags = HEADER(enclosing)->ov_flags;
        CHECK ("Not forwarded", !(HEADER (enclosing)->ov_size & B_FWD));

        if (
            flags & EO_OLD &&			/* Object is old */
            !(flags & EO_REM)	&&		/* Not remembered */
            refers_new_object(target)	/* And copied refers to new objects */
        )
            erembq(enclosing);			/* Then remember the enclosing object */
#endif /* ISE_GC */
    }
}
Exemple #3
0
rt_private EIF_REFERENCE duplicate(EIF_REFERENCE source, EIF_REFERENCE enclosing, rt_uint_ptr offset)
/* Object to be duplicated */
/* Object where attachment is made */
/* Offset within enclosing where attachment is made */
{
    /* Duplicate the source object (shallow duplication) and attach the freshly
     * allocated copy at the address pointed to by receiver, which is protected
     * against GC movements. Returns the address of the cloned object.
     */

    RT_GET_CONTEXT
    union overhead *zone;			/* Malloc info zone */
    uint16 flags;					/* Object's flags */
    rt_uint_ptr size;					/* Object's size */
    EIF_REFERENCE *hash_zone;				/* Hash table entry recording duplication */
    EIF_REFERENCE clone;					/* Where clone is allocated */

    REQUIRE("source not null", source);
    REQUIRE("enclosing not null", enclosing);

    zone = HEADER(source);			/* Where eif_malloc stores its information */
    flags = zone->ov_flags;			/* Eiffel flags */

    if (flags & EO_SPEC) {
        size = RT_SPECIAL_VISIBLE_SIZE(source);
    } else {
        size = EIF_Size(zone->ov_dtype);
    }

    clone = eif_access(map_next());				/* Get next stacked object */
    *(EIF_REFERENCE *)  (enclosing + offset) = clone;	/* Attach new object */
    hash_zone = hash_search(&hclone, source);	/* Get an hash table entry */
    CHECK("Enough space", HEADER(clone)->ov_size >= size);
    memcpy (clone, source, size);				/* Block copy */
    *hash_zone = clone;					/* Fill it in with the clone address */

#ifdef ISE_GC
    /* Once the duplication is done, the receiving object might refer to a new
     * object (a newly allocated object is always new), and thus aging tests
     * must be performed, to eventually remember the enclosing object of the
     * receiver.
     */

    flags = HEADER(enclosing)->ov_flags;

    if (!(flags & EO_OLD))				/* Receiver is a new object */
        return clone;					/* No aging tests necessary */

    if (HEADER (clone)->ov_flags & EO_OLD)		/* Old object with old reference.*/
        return clone;					/* No further action necessary */

    CHECK ("Object is old and has reference to new one",
           (flags & EO_OLD) && !(HEADER (clone)->ov_flags & EO_OLD));

    if (flags & EO_REM)					/* Old object is already remembered */
        return clone;					/* No further action necessary */
    else
        erembq(enclosing);				/* Then remember the enclosing object */

#endif /* ISE_GC */

    return clone;
}