Skip to content

Commit

Permalink
Merge pull request #222 from MatthewFluet/heap-predicates
Browse files Browse the repository at this point in the history
Fix heap invariant predicates

Previously, the `isPointerInOldGen` and `isPointerInNursery`
predicates checked that the object pointer is strictly less than
`s->heap.start + s->heap.oldGenSize` and `s->frontier`, respectively.

With #219 (forward pointer in header), 0-byte objects are
allowed and the above checks are insufficient.  In particular,
immediately after allocating a 0-byte object, the object pointer is
equal to the frontier.  Now (381a47e and 437cdaa), the
`isPointerInOldGen` and `isPointerInNursery` predicates are revised to
check that the pointer less than or equal to `s->heap.start +
s->heap.oldGenSize` and `s->frontier`, respectively.


Previously, the `GC_memmove` function asserted that the src, dst, and
size values were aligned.  With #192 (array copy prims) a
GC_memmove may be invoked with arbitrary src, dst, and size values.
Now (30a3968), the `GC_memmove` function does not assert alignment for
src, dst, and size.  For consistency, neither does `GC_memcpy`.
  • Loading branch information
MatthewFluet committed Dec 3, 2017
2 parents 8fed932 + 30a3968 commit 90cbe1c
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 23 deletions.
7 changes: 4 additions & 3 deletions runtime/gc/heap_predicates.c
@@ -1,4 +1,4 @@
/* Copyright (C) 2012 Matthew Fluet.
/* Copyright (C) 2012,2017 Matthew Fluet.
* Copyright (C) 2005 Henry Cejtin, Matthew Fluet, Suresh
* Jagannathan, and Stephen Weeks.
*
Expand All @@ -9,12 +9,13 @@
bool isPointerInOldGen (GC_state s, pointer p) {
return (not (isPointer (p))
or (s->heap.start <= p
and p < s->heap.start + s->heap.oldGenSize));
and p <= s->heap.start + s->heap.oldGenSize));
}

bool isPointerInNursery (GC_state s, pointer p) {
return (not (isPointer (p))
or (s->heap.nursery <= p and p < s->frontier));
or (s->heap.nursery <= p
and p <= s->frontier));
}

#if ASSERT
Expand Down
6 changes: 4 additions & 2 deletions runtime/gc/invariant.c
@@ -1,4 +1,4 @@
/* Copyright (C) 2011-2012 Matthew Fluet.
/* Copyright (C) 2011-2012,2017 Matthew Fluet.
* Copyright (C) 1999-2007 Henry Cejtin, Matthew Fluet, Suresh
* Jagannathan, and Stephen Weeks.
* Copyright (C) 1997-2000 NEC Research Institute.
Expand All @@ -10,11 +10,13 @@
#if ASSERT
void assertIsObjptrInFromSpace (GC_state s, objptr *opp) {
assert (isObjptrInFromSpace (s, *opp));
unless (isObjptrInFromSpace (s, *opp))
unless (isObjptrInFromSpace (s, *opp)) {
displayGCState (s, stderr);
die ("gc.c: assertIsObjptrInFromSpace "
"opp = "FMTPTR" "
"*opp = "FMTOBJPTR"\n",
(uintptr_t)opp, *opp);
}
/* The following checks that intergenerational pointers have the
* appropriate card marked. Unfortunately, it doesn't work because
* for stacks, the card containing the beginning of the stack is
Expand Down
30 changes: 20 additions & 10 deletions runtime/gc/object-size.c
@@ -1,4 +1,4 @@
/* Copyright (C) 2016 Matthew Fluet.
/* Copyright (C) 2016-2017 Matthew Fluet.
* Copyright (C) 1999-2007 Henry Cejtin, Matthew Fluet, Suresh
* Jagannathan, and Stephen Weeks.
* Copyright (C) 1997-2000 NEC Research Institute.
Expand All @@ -24,25 +24,35 @@ size_t sizeofStackNoMetaData (__attribute__ ((unused)) GC_state s,
return result;
}

size_t sizeofObject (GC_state s, pointer p) {
size_t metaDataBytes, objectBytes;
void sizeofObjectAux (GC_state s, pointer p, size_t* metaDataBytes, size_t* objectBytes) {
GC_header header;
GC_objectTypeTag tag;
uint16_t bytesNonObjptrs, numObjptrs;

header = getHeader (p);
splitHeader (s, header, &tag, NULL, &bytesNonObjptrs, &numObjptrs);
if ((NORMAL_TAG == tag) or (WEAK_TAG == tag)) {
metaDataBytes = GC_NORMAL_METADATA_SIZE;
objectBytes = bytesNonObjptrs + (numObjptrs * OBJPTR_SIZE);
*metaDataBytes = GC_NORMAL_METADATA_SIZE;
*objectBytes = bytesNonObjptrs + (numObjptrs * OBJPTR_SIZE);
} else if (ARRAY_TAG == tag) {
metaDataBytes = GC_ARRAY_METADATA_SIZE;
objectBytes = sizeofArrayNoMetaData (s, getArrayLength (p),
bytesNonObjptrs, numObjptrs);
*metaDataBytes = GC_ARRAY_METADATA_SIZE;
*objectBytes = sizeofArrayNoMetaData (s, getArrayLength (p),
bytesNonObjptrs, numObjptrs);
} else { /* Stack. */
assert (STACK_TAG == tag);
metaDataBytes = GC_STACK_METADATA_SIZE;
objectBytes = sizeofStackNoMetaData (s, (GC_stack)p);
*metaDataBytes = GC_STACK_METADATA_SIZE;
*objectBytes = sizeofStackNoMetaData (s, (GC_stack)p);
}
}

size_t sizeofObject (GC_state s, pointer p) {
size_t metaDataBytes, objectBytes;
sizeofObjectAux(s, p, &metaDataBytes, &objectBytes);
return metaDataBytes + objectBytes;
}

size_t sizeofObjectNoMetaData (GC_state s, pointer p) {
size_t metaDataBytes, objectBytes;
sizeofObjectAux(s, p, &metaDataBytes, &objectBytes);
return objectBytes;
}
7 changes: 6 additions & 1 deletion runtime/gc/object-size.h
@@ -1,4 +1,4 @@
/* Copyright (C) 2016 Matthew Fluet.
/* Copyright (C) 2016-2017 Matthew Fluet.
* Copyright (C) 1999-2007 Henry Cejtin, Matthew Fluet, Suresh
* Jagannathan, and Stephen Weeks.
* Copyright (C) 1997-2000 NEC Research Institute.
Expand All @@ -13,6 +13,11 @@ static inline size_t sizeofArrayNoMetaData (GC_state s, GC_arrayLength numElemen
uint16_t bytesNonObjptrs, uint16_t numObjptrs);
static inline size_t sizeofStackNoMetaData (GC_state s, GC_stack stack);

static inline void sizeofObjectAux (GC_state s, pointer p,
size_t* metaDataBytes, size_t* objectBytes);

static inline size_t sizeofObject (GC_state s, pointer p);

static inline size_t sizeofObjectNoMetaData (GC_state s, pointer p);

#endif /* (defined (MLTON_GC_INTERNAL_FUNCS)) */
8 changes: 1 addition & 7 deletions runtime/gc/virtual-memory.c
@@ -1,4 +1,4 @@
/* Copyright (C) 2010 Matthew Fluet.
/* Copyright (C) 2010,2017 Matthew Fluet.
* Copyright (C) 1999-2008 Henry Cejtin, Matthew Fluet, Suresh
* Jagannathan, and Stephen Weeks.
* Copyright (C) 1997-2000 NEC Research Institute.
Expand All @@ -23,9 +23,6 @@ static inline void GC_memcpy (pointer src, pointer dst, size_t size) {
if (DEBUG_DETAILED)
fprintf (stderr, "GC_memcpy ("FMTPTR", "FMTPTR", %"PRIuMAX")\n",
(uintptr_t)src, (uintptr_t)dst, (uintmax_t)size);
assert (isAligned ((size_t)src, sizeof(unsigned int)));
assert (isAligned ((size_t)dst, sizeof(unsigned int)));
assert (isAligned (size, sizeof(unsigned int)));
assert (! (src <= dst and dst < src + size));
assert (! (dst <= src and src < dst + size));
memcpy (dst, src, size);
Expand All @@ -35,9 +32,6 @@ static inline void GC_memmove (pointer src, pointer dst, size_t size) {
if (DEBUG_DETAILED)
fprintf (stderr, "GC_memmove ("FMTPTR", "FMTPTR", %"PRIuMAX")\n",
(uintptr_t)src, (uintptr_t)dst, (uintmax_t)size);
assert (isAligned ((size_t)src, sizeof(unsigned int)));
assert (isAligned ((size_t)dst, sizeof(unsigned int)));
assert (isAligned (size, sizeof(unsigned int)));
if (src == dst)
return;
memmove (dst, src, size);
Expand Down

0 comments on commit 90cbe1c

Please sign in to comment.