aboutsummaryrefslogtreecommitdiffstats
path: root/mps/code
diff options
context:
space:
mode:
authorRichard Brooksby2012-09-07 23:48:14 +0100
committerRichard Brooksby2012-09-07 23:48:14 +0100
commit5a604a2f5197e7c769638fadb98aa41d88faef7f (patch)
tree8ba711da58dfd437f2cac5499dc01c31c07b8197 /mps/code
parent6c887280e43265b347cdd9056c86271ad81e8c2a (diff)
downloademacs-5a604a2f5197e7c769638fadb98aa41d88faef7f.tar.gz
emacs-5a604a2f5197e7c769638fadb98aa41d88faef7f.zip
Fixing bugs introduced by type puns passed through scanning methods, discovered by offsetting mps_ss_s from the beginning of scanstatestruct.
Adding a pseudo-target "find-puns" which, on FreeBSD mostly, prints useful warnings about strict aliasing rule violations. Fixing more strict aliasing rule violations found by the above. Copied from Perforce Change: 179358 ServerID: perforce.ravenbrook.com
Diffstat (limited to 'mps/code')
-rw-r--r--mps/code/comm.gmk12
-rw-r--r--mps/code/mpm.h20
-rw-r--r--mps/code/mpmtypes.h6
-rw-r--r--mps/code/poolamc.c8
-rw-r--r--mps/code/poolams.c4
-rw-r--r--mps/code/poolawl.c2
-rw-r--r--mps/code/poolsnc.c2
-rw-r--r--mps/code/root.c6
-rw-r--r--mps/code/trace.c41
9 files changed, 60 insertions, 41 deletions
diff --git a/mps/code/comm.gmk b/mps/code/comm.gmk
index 3b775882bc3..6ab9dec268c 100644
--- a/mps/code/comm.gmk
+++ b/mps/code/comm.gmk
@@ -498,6 +498,18 @@ $(PFM)/$(VARIETY)/%:
498 $(CC) $(CFLAGS) $(LINKFLAGS) -o $@ $^ $(LIBS) 498 $(CC) $(CFLAGS) $(LINKFLAGS) -o $@ $^ $(LIBS)
499 499
500 500
501# Special targets for development
502
503# Currently FreeBSD 7 GCC 4.2.1 is the best platform we have for warning
504# us about strict aliasing rule violations caused by type puns. This
505# target reveals them, and produces an assembler output file that can be
506# examined to see if they're actually dangerous. RB 2012-09-07
507
508find-puns: phony
509 { echo '#include "mps.c"'; echo '#include "fmtdy.c"'; } | \
510 gcc -S -fverbose-asm -ansi -pedantic -Wall -Wstrict-aliasing=2 -O3 -x c -o pun.s -
511
512
501# C. COPYRIGHT AND LICENSE 513# C. COPYRIGHT AND LICENSE
502# 514#
503# Copyright (C) 2001-2002 Ravenbrook Limited <http://www.ravenbrook.com/>. 515# Copyright (C) 2001-2002 Ravenbrook Limited <http://www.ravenbrook.com/>.
diff --git a/mps/code/mpm.h b/mps/code/mpm.h
index bdf4ba79d74..d43e92d10a2 100644
--- a/mps/code/mpm.h
+++ b/mps/code/mpm.h
@@ -154,9 +154,13 @@ extern Res WriteF_v(mps_lib_FILE *stream, va_list args);
154extern Res WriteF_firstformat_v(mps_lib_FILE *stream, 154extern Res WriteF_firstformat_v(mps_lib_FILE *stream,
155 const char *firstformat, va_list args); 155 const char *firstformat, va_list args);
156 156
157#if defined(DIAG_WITH_STREAM_AND_WRITEF)
157extern int Stream_fputc(int c, mps_lib_FILE *stream); 158extern int Stream_fputc(int c, mps_lib_FILE *stream);
158extern int Stream_fputs(const char *s, mps_lib_FILE *stream); 159extern int Stream_fputs(const char *s, mps_lib_FILE *stream);
159 160#else
161#define Stream_fputc mps_lib_fputc
162#define Stream_fputs mps_lib_fputs
163#endif
160 164
161 165
162/* Miscellaneous support -- see <code/mpm.c> */ 166/* Miscellaneous support -- see <code/mpm.c> */
@@ -419,6 +423,8 @@ extern double TraceWorkFactor;
419 ZoneSet SCANwhite = ScanStateWhite(ss); \ 423 ZoneSet SCANwhite = ScanStateWhite(ss); \
420 RefSet SCANsummary = ScanStateUnfixedSummary(ss); \ 424 RefSet SCANsummary = ScanStateUnfixedSummary(ss); \
421 Word SCANt; \ 425 Word SCANt; \
426 mps_addr_t SCANref; \
427 Res SCANres; \
422 { 428 {
423 429
424/* Equivalent to <code/mps.h> MPS_FIX1 */ 430/* Equivalent to <code/mps.h> MPS_FIX1 */
@@ -430,7 +436,17 @@ extern double TraceWorkFactor;
430 436
431/* Equivalent to <code/mps.h> MPS_FIX2 */ 437/* Equivalent to <code/mps.h> MPS_FIX2 */
432 438
433#define TRACE_FIX2(ss, refIO) _mps_fix2((mps_ss_t)(ss), (mps_addr_t *)(refIO)) 439/* TODO: The ref is copied to avoid breaking strict aliasing rules that could
440 well affect optimised scan loops. This code could be improved by
441 returning the fixed ref as a result and using longjmp to signal errors,
442 and that might well improve all scan loops too. The problem is whether
443 some embedded client platforms support longjmp. RB 2012-09-07 */
444
445#define TRACE_FIX2(ss, refIO) \
446 (SCANref = (mps_addr_t)*(refIO), \
447 SCANres = _mps_fix2(&(ss)->ss_s, &SCANref), \
448 *(refIO) = SCANref, \
449 SCANres)
434 450
435/* Equivalent to <code/mps.h> MPS_FIX */ 451/* Equivalent to <code/mps.h> MPS_FIX */
436 452
diff --git a/mps/code/mpmtypes.h b/mps/code/mpmtypes.h
index a15098c53ee..b1853178cbb 100644
--- a/mps/code/mpmtypes.h
+++ b/mps/code/mpmtypes.h
@@ -246,7 +246,7 @@ typedef struct TraceMessageStruct *TraceMessage; /* trace end */
246/* .fmt-methods: These methods must match those defined in the */ 246/* .fmt-methods: These methods must match those defined in the */
247/* MPS C Interface. (See <code/mps.h#fmt-methods>.) */ 247/* MPS C Interface. (See <code/mps.h#fmt-methods>.) */
248 248
249typedef Res (*FormatScanMethod)(ScanState ss, Addr base, Addr limit); 249typedef Res (*FormatScanMethod)(mps_ss_t ss, Addr base, Addr limit);
250typedef Addr (*FormatSkipMethod)(Addr object); 250typedef Addr (*FormatSkipMethod)(Addr object);
251typedef void (*FormatMoveMethod)(Addr object, Addr to); 251typedef void (*FormatMoveMethod)(Addr object, Addr to);
252typedef Addr (*FormatIsMovedMethod)(Addr object); 252typedef Addr (*FormatIsMovedMethod)(Addr object);
@@ -259,8 +259,8 @@ typedef Addr (*FormatClassMethod)(Addr object);
259/* .root-methods: These methods must match those defined in the */ 259/* .root-methods: These methods must match those defined in the */
260/* MPS C Interface. (See <code/mps.h#root-methods>.) */ 260/* MPS C Interface. (See <code/mps.h#root-methods>.) */
261 261
262typedef Res (*RootScanMethod)(ScanState ss, void *p, size_t s); 262typedef Res (*RootScanMethod)(mps_ss_t ss, void *p, size_t s);
263typedef Res (*RootScanRegMethod)(ScanState ss, Thread thread, void *p, size_t s); 263typedef Res (*RootScanRegMethod)(mps_ss_t ss, Thread thread, void *p, size_t s);
264 264
265 265
266/* CONSTANTS */ 266/* CONSTANTS */
diff --git a/mps/code/poolamc.c b/mps/code/poolamc.c
index c4500a811dd..fc71144ab84 100644
--- a/mps/code/poolamc.c
+++ b/mps/code/poolamc.c
@@ -1453,7 +1453,7 @@ static Res amcScanNailedOnce(Bool *totalReturn, Bool *moreReturn,
1453 Addr q; 1453 Addr q;
1454 q = (*format->skip)(p); 1454 q = (*format->skip)(p);
1455 if(amcNailGetMark(seg, p)) { 1455 if(amcNailGetMark(seg, p)) {
1456 res = (*format->scan)(ss, p, q); 1456 res = (*format->scan)(&ss->ss_s, p, q);
1457 if(res != ResOK) { 1457 if(res != ResOK) {
1458 *totalReturn = FALSE; 1458 *totalReturn = FALSE;
1459 *moreReturn = TRUE; 1459 *moreReturn = TRUE;
@@ -1476,7 +1476,7 @@ static Res amcScanNailedOnce(Bool *totalReturn, Bool *moreReturn,
1476 Addr q; 1476 Addr q;
1477 q = (*format->skip)(p); 1477 q = (*format->skip)(p);
1478 if(amcNailGetMark(seg, p)) { 1478 if(amcNailGetMark(seg, p)) {
1479 res = (*format->scan)(ss, p, q); 1479 res = (*format->scan)(&ss->ss_s, p, q);
1480 if(res != ResOK) { 1480 if(res != ResOK) {
1481 *totalReturn = FALSE; 1481 *totalReturn = FALSE;
1482 *moreReturn = TRUE; 1482 *moreReturn = TRUE;
@@ -1601,7 +1601,7 @@ static Res AMCScan(Bool *totalReturn, ScanState ss, Pool pool, Seg seg)
1601 *totalReturn = TRUE; 1601 *totalReturn = TRUE;
1602 return ResOK; 1602 return ResOK;
1603 } 1603 }
1604 res = (*format->scan)(ss, base, limit); 1604 res = (*format->scan)(&ss->ss_s, base, limit);
1605 if(res != ResOK) { 1605 if(res != ResOK) {
1606 *totalReturn = FALSE; 1606 *totalReturn = FALSE;
1607 return res; 1607 return res;
@@ -1615,7 +1615,7 @@ static Res AMCScan(Bool *totalReturn, ScanState ss, Pool pool, Seg seg)
1615 AVER(SegBase(seg) <= base); 1615 AVER(SegBase(seg) <= base);
1616 AVER(base <= AddrAdd(SegLimit(seg), format->headerSize)); 1616 AVER(base <= AddrAdd(SegLimit(seg), format->headerSize));
1617 if(base < limit) { 1617 if(base < limit) {
1618 res = (*format->scan)(ss, base, limit); 1618 res = (*format->scan)(&ss->ss_s, base, limit);
1619 if(res != ResOK) { 1619 if(res != ResOK) {
1620 *totalReturn = FALSE; 1620 *totalReturn = FALSE;
1621 return res; 1621 return res;
diff --git a/mps/code/poolams.c b/mps/code/poolams.c
index 880e20f7bb0..34e07fceccc 100644
--- a/mps/code/poolams.c
+++ b/mps/code/poolams.c
@@ -1237,7 +1237,7 @@ static Res amsScanObject(Seg seg, Index i, Addr p, Addr next, void *clos)
1237 1237
1238 /* @@@@ This isn't quite right for multiple traces. */ 1238 /* @@@@ This isn't quite right for multiple traces. */
1239 if (closure->scanAllObjects || AMS_IS_GREY(seg, i)) { 1239 if (closure->scanAllObjects || AMS_IS_GREY(seg, i)) {
1240 res = (*format->scan)(closure->ss, 1240 res = (*format->scan)(&closure->ss->ss_s,
1241 AddrAdd(p, format->headerSize), 1241 AddrAdd(p, format->headerSize),
1242 AddrAdd(next, format->headerSize)); 1242 AddrAdd(next, format->headerSize));
1243 if (res != ResOK) 1243 if (res != ResOK)
@@ -1331,7 +1331,7 @@ Res AMSScan(Bool *totalReturn, ScanState ss, Pool pool, Seg seg)
1331 next = AddrAdd(p, alignment); 1331 next = AddrAdd(p, alignment);
1332 } 1332 }
1333 j = AMS_ADDR_INDEX(seg, next); 1333 j = AMS_ADDR_INDEX(seg, next);
1334 res = (*format->scan)(ss, clientP, clientNext); 1334 res = (*format->scan)(&ss->ss_s, clientP, clientNext);
1335 if (res != ResOK) { 1335 if (res != ResOK) {
1336 /* <design/poolams/#marked.scan.fail> */ 1336 /* <design/poolams/#marked.scan.fail> */
1337 amsseg->marksChanged = TRUE; 1337 amsseg->marksChanged = TRUE;
diff --git a/mps/code/poolawl.c b/mps/code/poolawl.c
index e1fcbd94b4e..da63a4374d3 100644
--- a/mps/code/poolawl.c
+++ b/mps/code/poolawl.c
@@ -820,7 +820,7 @@ static Res awlScanObject(Arena arena, AWL awl, ScanState ss,
820 SegSetSummary(dependentSeg, RefSetUNIV); 820 SegSetSummary(dependentSeg, RefSetUNIV);
821 } 821 }
822 822
823 res = (*format->scan)(ss, base, limit); 823 res = (*format->scan)(&ss->ss_s, base, limit);
824 if (res == ResOK) 824 if (res == ResOK)
825 ss->scannedSize += AddrOffset(base, limit); 825 ss->scannedSize += AddrOffset(base, limit);
826 826
diff --git a/mps/code/poolsnc.c b/mps/code/poolsnc.c
index 657c0f54843..4dcb7115902 100644
--- a/mps/code/poolsnc.c
+++ b/mps/code/poolsnc.c
@@ -516,7 +516,7 @@ static Res SNCScan(Bool *totalReturn, ScanState ss, Pool pool, Seg seg)
516 } 516 }
517 517
518 if (base < limit) { 518 if (base < limit) {
519 res = (*format->scan)(ss, base, limit); 519 res = (*format->scan)(&ss->ss_s, base, limit);
520 if (res != ResOK) { 520 if (res != ResOK) {
521 *totalReturn = FALSE; 521 *totalReturn = FALSE;
522 return res; 522 return res;
diff --git a/mps/code/root.c b/mps/code/root.c
index 9484c4bfa36..9ce385a124c 100644
--- a/mps/code/root.c
+++ b/mps/code/root.c
@@ -478,20 +478,20 @@ Res RootScan(ScanState ss, Root root)
478 break; 478 break;
479 479
480 case RootFUN: 480 case RootFUN:
481 res = (*root->the.fun.scan)(ss, root->the.fun.p, root->the.fun.s); 481 res = (*root->the.fun.scan)(&ss->ss_s, root->the.fun.p, root->the.fun.s);
482 if (res != ResOK) 482 if (res != ResOK)
483 goto failScan; 483 goto failScan;
484 break; 484 break;
485 485
486 case RootREG: 486 case RootREG:
487 res = (*root->the.reg.scan)(ss, root->the.reg.thread, 487 res = (*root->the.reg.scan)(&ss->ss_s, root->the.reg.thread,
488 root->the.reg.p, root->the.reg.s); 488 root->the.reg.p, root->the.reg.s);
489 if (res != ResOK) 489 if (res != ResOK)
490 goto failScan; 490 goto failScan;
491 break; 491 break;
492 492
493 case RootFMT: 493 case RootFMT:
494 res = (*root->the.fmt.scan)(ss, root->the.fmt.base, root->the.fmt.limit); 494 res = (*root->the.fmt.scan)(&ss->ss_s, root->the.fmt.base, root->the.fmt.limit);
495 ss->scannedSize += AddrOffset(root->the.fmt.base, root->the.fmt.limit); 495 ss->scannedSize += AddrOffset(root->the.fmt.base, root->the.fmt.limit);
496 if (res != ResOK) 496 if (res != ResOK)
497 goto failScan; 497 goto failScan;
diff --git a/mps/code/trace.c b/mps/code/trace.c
index 09fb803b2cc..ffe800e151e 100644
--- a/mps/code/trace.c
+++ b/mps/code/trace.c
@@ -1295,26 +1295,31 @@ void TraceSegAccess(Arena arena, Seg seg, AccessSet mode)
1295} 1295}
1296 1296
1297 1297
1298/* TraceFix2 -- second stage of fixing a reference 1298/* _mps_fix2 (a.k.a. "TraceFix") -- second stage of fixing a reference
1299 * 1299 *
1300 * TraceFix is on the [critical path](../design/critical-path.txt). A 1300 * _mps_fix2 is on the [critical path](../design/critical-path.txt). A
1301 * one-instruction difference in the early parts of this code will have a 1301 * one-instruction difference in the early parts of this code will have a
1302 * significant impact on overall run time. The priority is to eliminate 1302 * significant impact on overall run time. The priority is to eliminate
1303 * irrelevant references early and fast using the colour information stored 1303 * irrelevant references early and fast using the colour information stored
1304 * in the tract table. 1304 * in the tract table.
1305 *
1306 * The name "TraceFix" is pervasive in the MPS and its documents to describe
1307 * this function. Optimisation and strict aliasing rules have meant that we
1308 * need to use the external name for it here.
1305 */ 1309 */
1306 1310
1307static Res TraceFix2(ScanState ss, Ref *refIO) 1311mps_res_t _mps_fix2(mps_ss_t mps_ss, mps_addr_t *mps_ref_io)
1308{ 1312{
1313 ScanState ss = PARENT(ScanStateStruct, ss_s, mps_ss);
1309 Ref ref; 1314 Ref ref;
1310 Tract tract; 1315 Tract tract;
1311 1316
1312 /* Special AVER macros are used on the critical path. */ 1317 /* Special AVER macros are used on the critical path. */
1313 /* See <design/trace/#fix.noaver> */ 1318 /* See <design/trace/#fix.noaver> */
1314 AVERT_CRITICAL(ScanState, ss); 1319 AVERT_CRITICAL(ScanState, ss);
1315 AVER_CRITICAL(refIO != NULL); 1320 AVER_CRITICAL(mps_ref_io != NULL);
1316 1321
1317 ref = *refIO; 1322 ref = (Ref)*mps_ref_io;
1318 1323
1319 /* The zone test should already have been passed by MPS_FIX1 in mps.h. */ 1324 /* The zone test should already have been passed by MPS_FIX1 in mps.h. */
1320 AVER_CRITICAL(ZoneSetInter(ScanStateWhite(ss), 1325 AVER_CRITICAL(ZoneSetInter(ScanStateWhite(ss),
@@ -1322,7 +1327,7 @@ static Res TraceFix2(ScanState ss, Ref *refIO)
1322 ZoneSetEMPTY); 1327 ZoneSetEMPTY);
1323 1328
1324 STATISTIC(++ss->fixRefCount); 1329 STATISTIC(++ss->fixRefCount);
1325 EVENT4(TraceFix, ss, refIO, ref, ss->rank); 1330 EVENT4(TraceFix, ss, mps_ref_io, ref, ss->rank);
1326 1331
1327 TRACT_OF_ADDR(&tract, ss->arena, ref); 1332 TRACT_OF_ADDR(&tract, ss->arena, ref);
1328 if(tract) { 1333 if(tract) {
@@ -1336,7 +1341,7 @@ static Res TraceFix2(ScanState ss, Ref *refIO)
1336 EVENT1(TraceFixSeg, seg); 1341 EVENT1(TraceFixSeg, seg);
1337 EVENT0(TraceFixWhite); 1342 EVENT0(TraceFixWhite);
1338 pool = TractPool(tract); 1343 pool = TractPool(tract);
1339 res = (*ss->fix)(pool, ss, seg, refIO); 1344 res = (*ss->fix)(pool, ss, seg, &ref);
1340 if(res != ResOK) { 1345 if(res != ResOK) {
1341 /* PoolFixEmergency should never fail. */ 1346 /* PoolFixEmergency should never fail. */
1342 AVER_CRITICAL(ss->fix != PoolFixEmergency); 1347 AVER_CRITICAL(ss->fix != PoolFixEmergency);
@@ -1347,7 +1352,7 @@ static Res TraceFix2(ScanState ss, Ref *refIO)
1347 * C: the code (here) already assumes this: it returns without 1352 * C: the code (here) already assumes this: it returns without
1348 * updating ss->fixedSummary. RHSK 2007-03-21. 1353 * updating ss->fixedSummary. RHSK 2007-03-21.
1349 */ 1354 */
1350 AVER(*refIO == ref); 1355 AVER(ref == (Ref)*mps_ref_io);
1351 return res; 1356 return res;
1352 } 1357 }
1353 } else { 1358 } else {
@@ -1378,27 +1383,13 @@ static Res TraceFix2(ScanState ss, Ref *refIO)
1378 } 1383 }
1379 1384
1380 /* See <design/trace/#fix.fixed.all> */ 1385 /* See <design/trace/#fix.fixed.all> */
1381 ss->fixedSummary = RefSetAdd(ss->arena, ss->fixedSummary, *refIO); 1386 ss->fixedSummary = RefSetAdd(ss->arena, ss->fixedSummary, ref);
1382 1387
1388 *mps_ref_io = (mps_addr_t)ref;
1383 return ResOK; 1389 return ResOK;
1384} 1390}
1385 1391
1386 1392
1387/* mps_fix2 -- external interface to TraceFix
1388 *
1389 * We rely on compiler inlining to make this equivalent to TraceFix, because
1390 * the name "TraceFix" is pervasive in the MPS. That's also why this
1391 * function is in trace.c and not mpsi.c.
1392 */
1393
1394mps_res_t _mps_fix2(mps_ss_t mps_ss, mps_addr_t *mps_ref_io)
1395{
1396 ScanState ss = PARENT(ScanStateStruct, ss_s, mps_ss);
1397 Ref *refIO = (Ref *)mps_ref_io;
1398 return TraceFix2(ss, refIO);
1399}
1400
1401
1402/* traceScanSingleRefRes -- scan a single reference, with result code */ 1393/* traceScanSingleRefRes -- scan a single reference, with result code */
1403 1394
1404static Res traceScanSingleRefRes(TraceSet ts, Rank rank, Arena arena, 1395static Res traceScanSingleRefRes(TraceSet ts, Rank rank, Arena arena,