mirror of
git://git.sv.gnu.org/emacs.git
synced 2025-12-18 20:00:36 -08:00
Catch-up merge from master sources to branch/2016-03-01/mvff-control.
Copied from Perforce Change: 189783 ServerID: perforce.ravenbrook.com
This commit is contained in:
commit
733b4e2072
132 changed files with 3945 additions and 1770 deletions
|
|
@ -5,7 +5,9 @@ anangc
|
|||
ananll
|
||||
ananmv
|
||||
fri3gc
|
||||
fri3ll
|
||||
fri6gc
|
||||
fri6ll
|
||||
lii3gc
|
||||
lii6gc
|
||||
lii6ll
|
||||
|
|
@ -49,3 +51,5 @@ tags
|
|||
9
|
||||
# Mac OS X Finder turds
|
||||
.DS_Store
|
||||
# Emacs backups
|
||||
*~
|
||||
|
|
|
|||
|
|
@ -127,8 +127,7 @@ static void test_main(void *marker, int interior, int stack)
|
|||
error("Couldn't register thread");
|
||||
|
||||
if (stack) {
|
||||
res = mps_root_create_reg(®_root, scheme_arena, mps_rank_ambig(), 0,
|
||||
thread, mps_stack_scan_ambig, marker, 0);
|
||||
res = mps_root_create_thread(®_root, scheme_arena, thread, marker);
|
||||
if (res != MPS_RES_OK)
|
||||
error("Couldn't create root");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ static mps_gen_param_s testChain[genCOUNT] = {
|
|||
#define objNULL ((mps_addr_t)MPS_WORD_CONST(0xDECEA5ED))
|
||||
|
||||
|
||||
static mps_arena_t arena;
|
||||
static mps_ap_t ap;
|
||||
static mps_addr_t exactRoots[exactRootsCOUNT];
|
||||
static mps_addr_t ambigRoots[ambigRootsCOUNT];
|
||||
|
|
@ -51,7 +52,7 @@ static unsigned long nCollsDone;
|
|||
|
||||
/* report -- report statistics from any messages */
|
||||
|
||||
static void report(mps_arena_t arena)
|
||||
static void report(void)
|
||||
{
|
||||
mps_message_type_t type;
|
||||
|
||||
|
|
@ -103,8 +104,10 @@ static mps_addr_t make(size_t rootsCount)
|
|||
|
||||
do {
|
||||
MPS_RESERVE_BLOCK(res, p, ap, size);
|
||||
if (res)
|
||||
if (res) {
|
||||
ArenaDescribe(arena, mps_lib_get_stderr(), 4);
|
||||
die(res, "MPS_RESERVE_BLOCK");
|
||||
}
|
||||
res = dylan_init(p, size, exactRoots, rootsCount);
|
||||
if (res)
|
||||
die(res, "dylan_init");
|
||||
|
|
@ -127,8 +130,7 @@ static void test_stepper(mps_addr_t object, mps_fmt_t fmt, mps_pool_t pool,
|
|||
|
||||
/* test -- the body of the test */
|
||||
|
||||
static void test(mps_arena_t arena, mps_pool_class_t pool_class,
|
||||
size_t roots_count)
|
||||
static void test(mps_pool_class_t pool_class, size_t roots_count)
|
||||
{
|
||||
mps_fmt_t format;
|
||||
mps_chain_t chain;
|
||||
|
|
@ -180,7 +182,7 @@ static void test(mps_arena_t arena, mps_pool_class_t pool_class,
|
|||
while (collections < collectionsCOUNT) {
|
||||
size_t r;
|
||||
|
||||
report(arena);
|
||||
report();
|
||||
if (collections != nCollsStart) {
|
||||
if (!described) {
|
||||
die(ArenaDescribe(arena, mps_lib_get_stdout(), 0), "ArenaDescribe");
|
||||
|
|
@ -276,7 +278,7 @@ static void test(mps_arena_t arena, mps_pool_class_t pool_class,
|
|||
*(int*)busy_init = -1; /* check that the buffer is still there */
|
||||
|
||||
if (objs % 1024 == 0) {
|
||||
report(arena);
|
||||
report();
|
||||
putchar('.');
|
||||
(void)fflush(stdout);
|
||||
}
|
||||
|
|
@ -299,7 +301,6 @@ static void test(mps_arena_t arena, mps_pool_class_t pool_class,
|
|||
int main(int argc, char *argv[])
|
||||
{
|
||||
size_t i, grainSize;
|
||||
mps_arena_t arena;
|
||||
mps_thr_t thread;
|
||||
|
||||
testlib_init(argc, argv);
|
||||
|
|
@ -312,16 +313,15 @@ int main(int argc, char *argv[])
|
|||
MPS_ARGS_BEGIN(args) {
|
||||
MPS_ARGS_ADD(args, MPS_KEY_ARENA_SIZE, scale * testArenaSIZE);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_ARENA_GRAIN_SIZE, grainSize);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_COMMIT_LIMIT, scale * testArenaSIZE);
|
||||
die(mps_arena_create_k(&arena, mps_arena_class_vm(), args), "arena_create");
|
||||
} MPS_ARGS_END(args);
|
||||
mps_message_type_enable(arena, mps_message_type_gc());
|
||||
mps_message_type_enable(arena, mps_message_type_gc_start());
|
||||
die(mps_thread_reg(&thread, arena), "thread_reg");
|
||||
test(arena, mps_class_amc(), exactRootsCOUNT);
|
||||
test(arena, mps_class_amcz(), 0);
|
||||
test(mps_class_amc(), exactRootsCOUNT);
|
||||
test(mps_class_amcz(), 0);
|
||||
mps_thread_dereg(thread);
|
||||
report(arena);
|
||||
report();
|
||||
mps_arena_destroy(arena);
|
||||
|
||||
printf("%s: Conclusion: Failed to find any defects.\n", argv[0]);
|
||||
|
|
|
|||
|
|
@ -251,7 +251,6 @@ int main(int argc, char *argv[])
|
|||
MPS_ARGS_BEGIN(args) {
|
||||
MPS_ARGS_ADD(args, MPS_KEY_ARENA_SIZE, testArenaSIZE);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_ARENA_GRAIN_SIZE, rnd_grain(testArenaSIZE));
|
||||
MPS_ARGS_ADD(args, MPS_KEY_COMMIT_LIMIT, testArenaSIZE);
|
||||
die(mps_arena_create_k(&arena, mps_arena_class_vm(), args), "arena_create");
|
||||
} MPS_ARGS_END(args);
|
||||
mps_message_type_enable(arena, mps_message_type_gc());
|
||||
|
|
|
|||
|
|
@ -139,8 +139,8 @@ static void *kid_thread(void *arg)
|
|||
closure_t cl = arg;
|
||||
|
||||
die(mps_thread_reg(&thread, (mps_arena_t)arena), "thread_reg");
|
||||
die(mps_root_create_reg(®_root, arena, mps_rank_ambig(), 0, thread,
|
||||
mps_stack_scan_ambig, marker, 0), "root_create");
|
||||
die(mps_root_create_thread(®_root, arena, thread, marker),
|
||||
"root_create");
|
||||
|
||||
die(mps_ap_create(&ap, cl->pool, mps_rank_exact()), "BufferCreate(fooey)");
|
||||
while(mps_collections(arena) < collectionsCOUNT) {
|
||||
|
|
@ -316,8 +316,8 @@ static void test_arena(int mode)
|
|||
&ambigRoots[0], ambigRootsCOUNT),
|
||||
"root_create_table(ambig)");
|
||||
die(mps_thread_reg(&thread, arena), "thread_reg");
|
||||
die(mps_root_create_reg(®_root, arena, mps_rank_ambig(), 0, thread,
|
||||
mps_stack_scan_ambig, marker, 0), "root_create");
|
||||
die(mps_root_create_thread(®_root, arena, thread, marker),
|
||||
"root_create");
|
||||
|
||||
die(mps_pool_create(&amc_pool, arena, mps_class_amc(), format, chain),
|
||||
"pool_create(amc)");
|
||||
|
|
|
|||
|
|
@ -209,7 +209,6 @@ int main(int argc, char *argv[])
|
|||
MPS_ARGS_BEGIN(args) {
|
||||
MPS_ARGS_ADD(args, MPS_KEY_ARENA_SIZE, testArenaSIZE);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_ARENA_GRAIN_SIZE, rnd_grain(testArenaSIZE));
|
||||
MPS_ARGS_ADD(args, MPS_KEY_COMMIT_LIMIT, 2 * testArenaSIZE);
|
||||
die(mps_arena_create_k(&arena, mps_arena_class_vm(), args), "arena_create");
|
||||
} MPS_ARGS_END(args);
|
||||
|
||||
|
|
|
|||
|
|
@ -267,8 +267,7 @@ static void *setup(void *v, size_t s)
|
|||
arena = guff->arena;
|
||||
thr = guff->thr;
|
||||
|
||||
die(mps_root_create_reg(&stack, arena, mps_rank_ambig(), 0, thr,
|
||||
mps_stack_scan_ambig, v, 0),
|
||||
die(mps_root_create_thread(&stack, arena, thr, v),
|
||||
"Root Create\n");
|
||||
die(mps_fmt_create_A(&dylanfmt, arena, dylan_fmt_A()),
|
||||
"Format Create\n");
|
||||
|
|
|
|||
|
|
@ -271,8 +271,7 @@ static void *setup(void *v, size_t s)
|
|||
arena = guff->arena;
|
||||
thr = guff->thr;
|
||||
|
||||
die(mps_root_create_reg(&stack, arena, mps_rank_ambig(), 0, thr,
|
||||
mps_stack_scan_ambig, v, 0),
|
||||
die(mps_root_create_thread(&stack, arena, thr, v),
|
||||
"Root Create\n");
|
||||
die(EnsureHeaderFormat(&dylanfmt, arena), "EnsureHeaderFormat");
|
||||
die(EnsureHeaderWeakFormat(&dylanweakfmt, arena), "EnsureHeaderWeakFormat");
|
||||
|
|
|
|||
|
|
@ -254,8 +254,7 @@ static void *setup(void *v, size_t s)
|
|||
arena = guff->arena;
|
||||
thr = guff->thr;
|
||||
|
||||
die(mps_root_create_reg(&stack, arena, mps_rank_ambig(), 0, thr,
|
||||
mps_stack_scan_ambig, v, 0),
|
||||
die(mps_root_create_thread(&stack, arena, thr, v),
|
||||
"Root Create\n");
|
||||
die(mps_fmt_create_A(&dylanfmt, arena, dylan_fmt_A()),
|
||||
"Format Create\n");
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
/* clock.h -- Fast clocks and timers
|
||||
*
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license.
|
||||
* $Id$
|
||||
*
|
||||
* .design: <design/clock/>.
|
||||
*/
|
||||
|
||||
#ifndef clock_h
|
||||
|
|
@ -176,7 +178,7 @@ typedef mps_clock_t EventClock;
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
# comm.gmk: COMMON GNUMAKEFILE FRAGMENT
|
||||
#
|
||||
# $Id$
|
||||
# Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
# Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license.
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
|
|
@ -148,7 +148,7 @@ ARFLAGS=rc$(ARFLAGSPFM)
|
|||
# platforms.
|
||||
|
||||
AMC = poolamc.c
|
||||
AMS = poolams.c poolamsi.c
|
||||
AMS = poolams.c
|
||||
AWL = poolawl.c
|
||||
LO = poollo.c
|
||||
SNC = poolsnc.c
|
||||
|
|
@ -201,6 +201,7 @@ MPMCOMMON = \
|
|||
root.c \
|
||||
sa.c \
|
||||
sac.c \
|
||||
scan.c \
|
||||
seg.c \
|
||||
shield.c \
|
||||
splay.c \
|
||||
|
|
@ -284,6 +285,7 @@ TEST_TARGETS=\
|
|||
sacss \
|
||||
segsmss \
|
||||
steptest \
|
||||
tagtest \
|
||||
teletest \
|
||||
walkt0 \
|
||||
zcoll \
|
||||
|
|
@ -317,10 +319,24 @@ $(addprefix $(PFM)/$(VARIETY)/,$(TEST_SUITES)): $(TEST_TARGETS)
|
|||
../tool/testrun.sh -s "$(notdir $@)" "$(PFM)/$(VARIETY)"
|
||||
|
||||
|
||||
# == MMQA test suite ==
|
||||
#
|
||||
# See test/README for documentation on running the MMQA test suite.
|
||||
|
||||
MMQA=perl test/qa -i ../code -l ../code/$(PFM)/$(VARIETY)/mps.o
|
||||
|
||||
$(PFM)/$(VARIETY)/testmmqa:
|
||||
$(MAKE) -f $(PFM).gmk VARIETY=$(VARIETY) TARGET=mps.o variety
|
||||
(if [ "$(VARIETY)" = "cool" ]; then cd ../test && $(MMQA) runset testsets/coolonly; fi)
|
||||
(cd ../test && $(MMQA) runset testsets/argerr)
|
||||
(cd ../test && $(MMQA) runset testsets/conerr)
|
||||
(cd ../test && $(MMQA) runset testsets/passing)
|
||||
|
||||
|
||||
# These convenience targets allow one to type "make foo" to build target
|
||||
# foo in selected varieties (or none, for the latter rule).
|
||||
|
||||
$(ALL_TARGETS) $(TEST_SUITES): phony
|
||||
$(ALL_TARGETS) $(TEST_SUITES) testmmqa: phony
|
||||
ifdef VARIETY
|
||||
$(MAKE) -f $(PFM).gmk TARGET=$@ variety
|
||||
else
|
||||
|
|
@ -511,6 +527,9 @@ $(PFM)/$(VARIETY)/sacss: $(PFM)/$(VARIETY)/sacss.o \
|
|||
$(PFM)/$(VARIETY)/segsmss: $(PFM)/$(VARIETY)/segsmss.o \
|
||||
$(FMTDYTSTOBJ) $(TESTLIBOBJ) $(PFM)/$(VARIETY)/mps.a
|
||||
|
||||
$(PFM)/$(VARIETY)/tagtest: $(PFM)/$(VARIETY)/tagtest.o \
|
||||
$(TESTLIBOBJ) $(PFM)/$(VARIETY)/mps.a
|
||||
|
||||
$(PFM)/$(VARIETY)/teletest: $(PFM)/$(VARIETY)/teletest.o \
|
||||
$(TESTLIBOBJ) $(PFM)/$(VARIETY)/mps.a
|
||||
|
||||
|
|
@ -662,7 +681,7 @@ find-puns: phony
|
|||
|
||||
# C. COPYRIGHT AND LICENSE
|
||||
#
|
||||
# Copyright (c) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
# Copyright (c) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
# All rights reserved. This is an open source license. Contact
|
||||
# Ravenbrook for commercial licensing options.
|
||||
#
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# commpre.nmk: FIRST COMMON FRAGMENT FOR PLATFORMS USING NMAKE -*- makefile -*-1
|
||||
#
|
||||
# $Id$
|
||||
# Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
# Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license.
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
|
|
@ -146,6 +146,7 @@ MPMCOMMON=\
|
|||
[mpm] \
|
||||
[mpsi] \
|
||||
[nailboard] \
|
||||
[policy] \
|
||||
[pool] \
|
||||
[poolabs] \
|
||||
[poolmfs] \
|
||||
|
|
@ -160,6 +161,7 @@ MPMCOMMON=\
|
|||
[root] \
|
||||
[sa] \
|
||||
[sac] \
|
||||
[scan] \
|
||||
[seg] \
|
||||
[shield] \
|
||||
[splay] \
|
||||
|
|
@ -174,7 +176,7 @@ MPMCOMMON=\
|
|||
[walk]
|
||||
PLINTH = [mpsliban] [mpsioan]
|
||||
AMC = [poolamc]
|
||||
AMS = [poolams] [poolamsi]
|
||||
AMS = [poolams]
|
||||
AWL = [poolawl]
|
||||
LO = [poollo]
|
||||
MVFF = [poolmvff]
|
||||
|
|
@ -330,7 +332,7 @@ LIBFLAGSCOOL =
|
|||
|
||||
# C. COPYRIGHT AND LICENSE
|
||||
#
|
||||
# Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
# Copyright (C) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
# All rights reserved. This is an open source license. Contact
|
||||
# Ravenbrook for commercial licensing options.
|
||||
#
|
||||
|
|
|
|||
|
|
@ -190,6 +190,36 @@ Arena FormatArena(Format format)
|
|||
}
|
||||
|
||||
|
||||
/* FormatScan -- scan formatted objects for references
|
||||
*
|
||||
* This is a wrapper for formatted objects scanning functions, which
|
||||
* should not otherwise be called directly from within the MPS. This
|
||||
* function checks arguments and takes care of accounting for the
|
||||
* scanned memory.
|
||||
*
|
||||
* c.f. TraceScanArea()
|
||||
*/
|
||||
|
||||
Res FormatScan(Format format, ScanState ss, Addr base, Addr limit)
|
||||
{
|
||||
/* TODO: How critical are these? */
|
||||
AVERT_CRITICAL(Format, format);
|
||||
AVERT_CRITICAL(ScanState, ss);
|
||||
AVER_CRITICAL(base != NULL);
|
||||
AVER_CRITICAL(limit != NULL);
|
||||
AVER_CRITICAL(base < limit);
|
||||
|
||||
/* TODO: EVENT here? */
|
||||
|
||||
/* scannedSize is accumulated whether or not format->scan succeeds,
|
||||
so it's safe to accumulate now so that we can tail-call
|
||||
format->scan. */
|
||||
ss->scannedSize += AddrOffset(base, limit);
|
||||
|
||||
return format->scan(&ss->ss_s, base, limit);
|
||||
}
|
||||
|
||||
|
||||
/* FormatDescribe -- describe a format */
|
||||
|
||||
Res FormatDescribe(Format format, mps_lib_FILE *stream, Count depth)
|
||||
|
|
|
|||
71
mps/code/fri3ll.gmk
Normal file
71
mps/code/fri3ll.gmk
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
# -*- makefile -*-
|
||||
#
|
||||
# fri3ll.gmk: BUILD FOR FreeBSD/i386/GCC PLATFORM
|
||||
#
|
||||
# $Id$
|
||||
# Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
|
||||
PFM = fri3ll
|
||||
|
||||
MPMPF = \
|
||||
lockix.c \
|
||||
prmcan.c \
|
||||
prmci3fr.c \
|
||||
protix.c \
|
||||
protsgix.c \
|
||||
pthrdext.c \
|
||||
span.c \
|
||||
ssixi3.c \
|
||||
thix.c \
|
||||
vmix.c
|
||||
|
||||
LIBS = -lm -pthread
|
||||
|
||||
include ll.gmk
|
||||
|
||||
# For SQLite3.
|
||||
LINKFLAGS += -L/usr/local/lib
|
||||
CFLAGSCOMPILER += -I/usr/local/include
|
||||
|
||||
include comm.gmk
|
||||
|
||||
|
||||
# C. COPYRIGHT AND LICENSE
|
||||
#
|
||||
# Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
# All rights reserved. This is an open source license. Contact
|
||||
# Ravenbrook for commercial licensing options.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
#
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# 3. Redistributions in any form must be accompanied by information on how
|
||||
# to obtain complete source code for this software and any accompanying
|
||||
# software that uses this software. The source code must either be
|
||||
# included in the distribution or be available for no more than the cost
|
||||
# of distribution plus a nominal fee, and must be freely redistributable
|
||||
# under reasonable conditions. For an executable file, complete source
|
||||
# code means the source code for all modules it contains. It does not
|
||||
# include source code for modules or files that typically accompany the
|
||||
# major components of the operating system on which the executable file
|
||||
# runs.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||
# PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
# COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
68
mps/code/fri6ll.gmk
Normal file
68
mps/code/fri6ll.gmk
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
# -*- makefile -*-
|
||||
#
|
||||
# fri6ll.gmk: BUILD FOR FreeBSD/x86-64/GCC PLATFORM
|
||||
#
|
||||
# $Id$
|
||||
# Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license.
|
||||
|
||||
PFM = fri6ll
|
||||
|
||||
MPMPF = lockix.c thix.c pthrdext.c vmix.c \
|
||||
protix.c protsgix.c prmcan.c prmci6fr.c ssixi6.c span.c
|
||||
|
||||
LIBS = -lm -pthread
|
||||
|
||||
include ll.gmk
|
||||
|
||||
# FIXME: We pun types through the MPS interface, setting off this warning.
|
||||
# Can we avoid this? The puns might indeed be dangerous.
|
||||
#CFLAGSCOMPILER += -Wno-strict-aliasing
|
||||
|
||||
# For SQLite3.
|
||||
LINKFLAGS += -L/usr/local/lib
|
||||
CFLAGSCOMPILER += -I/usr/local/include
|
||||
|
||||
CC = cc
|
||||
|
||||
include comm.gmk
|
||||
|
||||
|
||||
# C. COPYRIGHT AND LICENSE
|
||||
#
|
||||
# Copyright (C) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
# All rights reserved. This is an open source license. Contact
|
||||
# Ravenbrook for commercial licensing options.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
#
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# 3. Redistributions in any form must be accompanied by information on how
|
||||
# to obtain complete source code for this software and any accompanying
|
||||
# software that uses this software. The source code must either be
|
||||
# included in the distribution or be available for no more than the cost
|
||||
# of distribution plus a nominal fee, and must be freely redistributable
|
||||
# under reasonable conditions. For an executable file, complete source
|
||||
# code means the source code for all modules it contains. It does not
|
||||
# include source code for modules or files that typically accompany the
|
||||
# major components of the operating system on which the executable file
|
||||
# runs.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||
# PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
# COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
|
@ -176,10 +176,8 @@ static void *start(void *p) {
|
|||
gcthread_t thread = p;
|
||||
void *marker;
|
||||
RESMUST(mps_thread_reg(&thread->mps_thread, arena));
|
||||
RESMUST(mps_root_create_reg(&thread->reg_root, arena,
|
||||
mps_rank_ambig(), (mps_rm_t)0,
|
||||
thread->mps_thread, &mps_stack_scan_ambig,
|
||||
&marker, (size_t)0));
|
||||
RESMUST(mps_root_create_thread(&thread->reg_root, arena,
|
||||
thread->mps_thread, &marker));
|
||||
RESMUST(mps_ap_create_k(&thread->ap, pool, mps_args_none));
|
||||
thread->fn(thread);
|
||||
mps_ap_destroy(thread->ap);
|
||||
|
|
|
|||
|
|
@ -1,83 +0,0 @@
|
|||
/* lo.h: LEAF OBJECT POOL CLASS INTERFACE
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* The Leaf Object PoolClass is an automatically managed (ie garbage
|
||||
* collected) pool for managing "leaf" objects. Leaf objects are
|
||||
* objects that have no references or no references that need tracing
|
||||
* (ie the objects they refer too are non-moving and are manually
|
||||
* managed).
|
||||
*
|
||||
* This Class has the following features:
|
||||
*
|
||||
* Approximately 6% (asymptotically) space overhead on managed objects.
|
||||
*
|
||||
* Automatically reclaims memory used by objects no longer reachable
|
||||
* from the roots.
|
||||
*
|
||||
* Non-moving. References to objects in this pool will never change
|
||||
* due to "fixing".
|
||||
*
|
||||
* Buffers will always "commit". When allocating using a buffer,
|
||||
* commit will never fail.
|
||||
*
|
||||
* The following caveat applies:
|
||||
*
|
||||
* Space and time performance will degrade when fragmentation
|
||||
* increases.
|
||||
*/
|
||||
|
||||
#ifndef lo_h
|
||||
#define lo_h
|
||||
|
||||
#include "mpm.h"
|
||||
|
||||
typedef struct LOStruct *LO;
|
||||
|
||||
extern PoolClass PoolClassLO(void);
|
||||
|
||||
#endif /* lo_h */
|
||||
|
||||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2002 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Redistributions in any form must be accompanied by information on how
|
||||
* to obtain complete source code for this software and any accompanying
|
||||
* software that uses this software. The source code must either be
|
||||
* included in the distribution or be available for no more than the cost
|
||||
* of distribution plus a nominal fee, and must be freely redistributable
|
||||
* under reasonable conditions. For an executable file, complete source
|
||||
* code means the source code for all modules it contains. It does not
|
||||
* include source code for modules or files that typically accompany the
|
||||
* major components of the operating system on which the executable file
|
||||
* runs.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
/* locus.c: LOCUS MANAGER
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* DESIGN
|
||||
*
|
||||
|
|
@ -10,7 +10,7 @@
|
|||
* collection strategy.
|
||||
*/
|
||||
|
||||
#include "chain.h"
|
||||
#include "locus.h"
|
||||
#include "ring.h"
|
||||
#include "mpm.h"
|
||||
#include "mpstd.h"
|
||||
|
|
@ -766,7 +766,7 @@ Bool LocusCheck(Arena arena)
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
/* chain.h: GENERATION CHAINS
|
||||
/* locus.h: GENERATION CHAINS
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license.
|
||||
*/
|
||||
|
||||
#ifndef chain_h
|
||||
#define chain_h
|
||||
#ifndef locus_h
|
||||
#define locus_h
|
||||
|
||||
#include "mpmtypes.h"
|
||||
#include "ring.h"
|
||||
|
|
@ -108,12 +108,12 @@ extern void PoolGenAccountForSegSplit(PoolGen pgen);
|
|||
extern void PoolGenAccountForSegMerge(PoolGen pgen);
|
||||
extern Res PoolGenDescribe(PoolGen gen, mps_lib_FILE *stream, Count depth);
|
||||
|
||||
#endif /* chain_h */
|
||||
#endif /* locus_h */
|
||||
|
||||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
@ -473,10 +473,9 @@ extern double TraceWorkFactor;
|
|||
} \
|
||||
END
|
||||
|
||||
extern Res TraceScanArea(ScanState ss, Addr *base, Addr *limit);
|
||||
extern Res TraceScanAreaTagged(ScanState ss, Addr *base, Addr *limit);
|
||||
extern Res TraceScanAreaMasked(ScanState ss,
|
||||
Addr *base, Addr *limit, Word mask);
|
||||
extern Res TraceScanArea(ScanState ss, Word *base, Word *limit,
|
||||
mps_area_scan_t scan_area,
|
||||
void *closure);
|
||||
extern void TraceScanSingleRef(TraceSet ts, Rank rank, Arena arena,
|
||||
Seg seg, Ref *refIO);
|
||||
|
||||
|
|
@ -860,6 +859,7 @@ extern Res FormatCreate(Format *formatReturn, Arena arena, ArgList args);
|
|||
extern void FormatDestroy(Format format);
|
||||
extern Arena FormatArena(Format format);
|
||||
extern Res FormatDescribe(Format format, mps_lib_FILE *stream, Count depth);
|
||||
extern Res FormatScan(Format format, ScanState ss, Addr base, Addr limit);
|
||||
|
||||
|
||||
/* Reference Interface -- see <code/ref.c> */
|
||||
|
|
@ -962,17 +962,26 @@ extern void LDMerge(mps_ld_t ld, Arena arena, mps_ld_t from);
|
|||
|
||||
/* Root Interface -- see <code/root.c> */
|
||||
|
||||
extern Res RootCreateTable(Root *rootReturn, Arena arena,
|
||||
extern Res RootCreateArea(Root *rootReturn, Arena arena,
|
||||
Rank rank, RootMode mode,
|
||||
Addr *base, Addr *limit);
|
||||
extern Res RootCreateTableMasked(Root *rootReturn, Arena arena,
|
||||
Word *base, Word *limit,
|
||||
mps_area_scan_t scan_area,
|
||||
void *closure);
|
||||
extern Res RootCreateAreaTagged(Root *rootReturn, Arena arena,
|
||||
Rank rank, RootMode mode,
|
||||
Addr *base, Addr *limit,
|
||||
Word mask);
|
||||
extern Res RootCreateReg(Root *rootReturn, Arena arena,
|
||||
Word *base, Word *limit,
|
||||
mps_area_scan_t scan_area,
|
||||
Word mask, Word pattern);
|
||||
extern Res RootCreateThread(Root *rootReturn, Arena arena,
|
||||
Rank rank, Thread thread,
|
||||
mps_reg_scan_t scan,
|
||||
void *p, size_t s);
|
||||
mps_area_scan_t scan_area,
|
||||
void *closure,
|
||||
Word *stackCold);
|
||||
extern Res RootCreateThreadTagged(Root *rootReturn, Arena arena,
|
||||
Rank rank, Thread thread,
|
||||
mps_area_scan_t scan_area,
|
||||
Word mask, Word pattern,
|
||||
Word *stackCold);
|
||||
extern Res RootCreateFmt(Root *rootReturn, Arena arena,
|
||||
Rank rank, RootMode mode,
|
||||
mps_fmt_scan_t scan,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* mpmst.h: MEMORY POOL MANAGER DATA STRUCTURES
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license.
|
||||
* Portions copyright (C) 2001 Global Graphics Software.
|
||||
*
|
||||
* .design: This header file crosses module boundaries. The relevant
|
||||
|
|
@ -26,7 +26,7 @@
|
|||
|
||||
#include "protocol.h"
|
||||
#include "ring.h"
|
||||
#include "chain.h"
|
||||
#include "locus.h"
|
||||
#include "splay.h"
|
||||
#include "meter.h"
|
||||
|
||||
|
|
@ -798,7 +798,7 @@ typedef struct mps_arena_s {
|
|||
|
||||
Bool emergency; /* garbage collect in emergency mode? */
|
||||
|
||||
Addr *stackAtArenaEnter; /* NULL or top of client stack, in the thread */
|
||||
Word *stackAtArenaEnter; /* NULL or hot end of client stack, in the thread */
|
||||
/* that then entered the MPS. */
|
||||
|
||||
Sig sig;
|
||||
|
|
@ -815,7 +815,7 @@ typedef struct AllocPatternStruct {
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -359,9 +359,10 @@ enum {
|
|||
|
||||
enum {
|
||||
RootFUN,
|
||||
RootTABLE,
|
||||
RootTABLE_MASKED,
|
||||
RootREG,
|
||||
RootAREA,
|
||||
RootAREA_TAGGED,
|
||||
RootTHREAD,
|
||||
RootTHREAD_TAGGED,
|
||||
RootFMT,
|
||||
RootLIMIT
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* mps.c: MEMORY POOL SYSTEM ALL-IN-ONE TRANSLATION UNIT
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (C) 2012-2014 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (C) 2012-2016 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* .purpose: This file can be compiled to create the complete MPS library in
|
||||
* a single compilation, allowing the compiler to apply global optimizations
|
||||
|
|
@ -45,6 +45,7 @@
|
|||
#include "poolabs.c"
|
||||
#include "trace.c"
|
||||
#include "traceanc.c"
|
||||
#include "scan.c"
|
||||
#include "root.c"
|
||||
#include "seg.c"
|
||||
#include "format.c"
|
||||
|
|
@ -85,7 +86,6 @@
|
|||
|
||||
#include "poolamc.c"
|
||||
#include "poolams.c"
|
||||
#include "poolamsi.c"
|
||||
#include "poolawl.c"
|
||||
#include "poollo.c"
|
||||
#include "poolsnc.c"
|
||||
|
|
@ -139,9 +139,9 @@
|
|||
#include "span.c" /* generic stack probe */
|
||||
#include "ssixi6.c" /* Posix on 64-bit Intel stack scan */
|
||||
|
||||
/* FreeBSD on 32-bit Intel built with GCC */
|
||||
/* FreeBSD on 32-bit Intel built with GCC or Clang */
|
||||
|
||||
#elif defined(MPS_PF_FRI3GC)
|
||||
#elif defined(MPS_PF_FRI3GC) || defined(MPS_PF_FRI3LL)
|
||||
|
||||
#include "lockix.c" /* Posix locks */
|
||||
#include "thix.c" /* Posix threading */
|
||||
|
|
@ -154,9 +154,9 @@
|
|||
#include "span.c" /* generic stack probe */
|
||||
#include "ssixi3.c" /* Posix on 32-bit Intel stack scan */
|
||||
|
||||
/* FreeBSD on 64-bit Intel built with GCC */
|
||||
/* FreeBSD on 64-bit Intel built with GCC or Clang */
|
||||
|
||||
#elif defined(MPS_PF_FRI6GC)
|
||||
#elif defined(MPS_PF_FRI6GC) || defined(MPS_PF_FRI6LL)
|
||||
|
||||
#include "lockix.c" /* Posix locks */
|
||||
#include "thix.c" /* Posix threading */
|
||||
|
|
@ -269,7 +269,7 @@
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2012-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2012-2016 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* mps.h: RAVENBROOK MEMORY POOL SYSTEM C INTERFACE
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license.
|
||||
* Portions copyright (c) 2002 Global Graphics Software.
|
||||
*
|
||||
* THIS HEADER IS NOT DOCUMENTATION.
|
||||
|
|
@ -102,7 +102,14 @@ _mps_ENUM_DEF(_mps_RES_ENUM, MPS_RES_)
|
|||
/* see design.mps.root-interface */
|
||||
/* see design.mps.format-interface */
|
||||
|
||||
typedef struct mps_scan_tag_s *mps_scan_tag_t;
|
||||
typedef struct mps_scan_tag_s {
|
||||
mps_word_t mask;
|
||||
mps_word_t pattern;
|
||||
} mps_scan_tag_s;
|
||||
|
||||
typedef mps_res_t (*mps_root_scan_t)(mps_ss_t, void *, size_t);
|
||||
typedef mps_res_t (*mps_area_scan_t)(mps_ss_t, void *, void *, void *);
|
||||
typedef mps_res_t (*mps_fmt_scan_t)(mps_ss_t, mps_addr_t, mps_addr_t);
|
||||
typedef mps_res_t (*mps_reg_scan_t)(mps_ss_t, mps_thr_t,
|
||||
void *, size_t);
|
||||
|
|
@ -491,7 +498,7 @@ extern size_t mps_pool_free_size(mps_pool_t);
|
|||
|
||||
/* Chains */
|
||||
|
||||
/* .gen-param: This structure must match <code/chain.h#gen-param>. */
|
||||
/* .gen-param: This structure must match <code/locus.h#gen-param>. */
|
||||
typedef struct mps_gen_param_s {
|
||||
size_t mps_capacity;
|
||||
double mps_mortality;
|
||||
|
|
@ -671,6 +678,15 @@ extern mps_res_t mps_root_create_table_masked(mps_root_t *, mps_arena_t,
|
|||
mps_rank_t, mps_rm_t,
|
||||
mps_addr_t *, size_t,
|
||||
mps_word_t);
|
||||
extern mps_res_t mps_root_create_area(mps_root_t *, mps_arena_t,
|
||||
mps_rank_t, mps_rm_t,
|
||||
void *, void *,
|
||||
mps_area_scan_t, void *);
|
||||
extern mps_res_t mps_root_create_area_tagged(mps_root_t *, mps_arena_t,
|
||||
mps_rank_t, mps_rm_t,
|
||||
void *, void *,
|
||||
mps_area_scan_t,
|
||||
mps_word_t, mps_word_t);
|
||||
extern mps_res_t mps_root_create_fmt(mps_root_t *, mps_arena_t,
|
||||
mps_rank_t, mps_rm_t,
|
||||
mps_fmt_scan_t, mps_addr_t,
|
||||
|
|
@ -678,6 +694,18 @@ extern mps_res_t mps_root_create_fmt(mps_root_t *, mps_arena_t,
|
|||
extern mps_res_t mps_root_create_reg(mps_root_t *, mps_arena_t,
|
||||
mps_rank_t, mps_rm_t, mps_thr_t,
|
||||
mps_reg_scan_t, void *, size_t);
|
||||
extern mps_res_t mps_root_create_thread(mps_root_t *, mps_arena_t,
|
||||
mps_thr_t, void *);
|
||||
extern mps_res_t mps_root_create_thread_scanned(mps_root_t *, mps_arena_t,
|
||||
mps_rank_t, mps_rm_t, mps_thr_t,
|
||||
mps_area_scan_t,
|
||||
void *,
|
||||
void *);
|
||||
extern mps_res_t mps_root_create_thread_tagged(mps_root_t *, mps_arena_t,
|
||||
mps_rank_t, mps_rm_t, mps_thr_t,
|
||||
mps_area_scan_t,
|
||||
mps_word_t, mps_word_t,
|
||||
void *);
|
||||
extern void mps_root_destroy(mps_root_t);
|
||||
|
||||
extern mps_res_t mps_stack_scan_ambig(mps_ss_t, mps_thr_t,
|
||||
|
|
@ -791,6 +819,11 @@ extern void mps_pool_check_free_space(mps_pool_t);
|
|||
|
||||
/* Scanner Support */
|
||||
|
||||
extern mps_res_t mps_scan_area(mps_ss_t, void *, void *, void *);
|
||||
extern mps_res_t mps_scan_area_masked(mps_ss_t, void *, void *, void *);
|
||||
extern mps_res_t mps_scan_area_tagged(mps_ss_t, void *, void *, void *);
|
||||
extern mps_res_t mps_scan_area_tagged_or_zero(mps_ss_t, void *, void *, void *);
|
||||
|
||||
extern mps_res_t mps_fix(mps_ss_t, mps_addr_t *);
|
||||
|
||||
#define MPS_SCAN_BEGIN(ss) \
|
||||
|
|
@ -834,7 +867,7 @@ extern mps_res_t _mps_fix2(mps_ss_t, mps_addr_t *);
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -113,6 +113,7 @@
|
|||
22B2BC3B18B643B000C33E63 /* PBXTargetDependency */,
|
||||
3104B04A156D3AE4000A585A /* PBXTargetDependency */,
|
||||
31D6009D156D404B00337B26 /* PBXTargetDependency */,
|
||||
314CB6EB1C6D272A0073CA42 /* PBXTargetDependency */,
|
||||
3114A62E156E94AA001E0AA3 /* PBXTargetDependency */,
|
||||
3114A6B9156E9763001E0AA3 /* PBXTargetDependency */,
|
||||
31D60063156D3F5C00337B26 /* PBXTargetDependency */,
|
||||
|
|
@ -216,6 +217,9 @@
|
|||
3104B04F156D3B09000A585A /* fmtdy.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CAC6156BE48D00753214 /* fmtdy.c */; };
|
||||
3104B050156D3B09000A585A /* fmtdytst.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CAC7156BE48D00753214 /* fmtdytst.c */; };
|
||||
3104B051156D3B09000A585A /* fmtno.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CACC156BE4C200753214 /* fmtno.c */; };
|
||||
31108A3E1C6B90E900E728EA /* testlib.c in Sources */ = {isa = PBXBuildFile; fileRef = 31EEAC9E156AB73400714D05 /* testlib.c */; };
|
||||
31108A411C6B90E900E728EA /* libmps.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 31EEABFB156AAF9D00714D05 /* libmps.a */; };
|
||||
31108A481C6B911B00E728EA /* tagtest.c in Sources */ = {isa = PBXBuildFile; fileRef = 31108A391C6B90D600E728EA /* tagtest.c */; };
|
||||
3114A59B156E914B001E0AA3 /* libmps.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 31EEABFB156AAF9D00714D05 /* libmps.a */; };
|
||||
3114A59C156E914F001E0AA3 /* testlib.c in Sources */ = {isa = PBXBuildFile; fileRef = 31EEAC9E156AB73400714D05 /* testlib.c */; };
|
||||
3114A5A2156E9168001E0AA3 /* locv.c in Sources */ = {isa = PBXBuildFile; fileRef = 3114A5A1156E9168001E0AA3 /* locv.c */; };
|
||||
|
|
@ -670,6 +674,13 @@
|
|||
remoteGlobalIDString = 3104B03C156D3AD7000A585A;
|
||||
remoteInfo = segsmss;
|
||||
};
|
||||
31108A3C1C6B90E900E728EA /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 31EEABFA156AAF9D00714D05;
|
||||
remoteInfo = mps;
|
||||
};
|
||||
3114A59D156E9156001E0AA3 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */;
|
||||
|
|
@ -866,6 +877,13 @@
|
|||
remoteGlobalIDString = 3114A6C5156E9815001E0AA3;
|
||||
remoteInfo = mpseventcnv;
|
||||
};
|
||||
314CB6EA1C6D272A0073CA42 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 31108A3A1C6B90E900E728EA;
|
||||
remoteInfo = tagtest;
|
||||
};
|
||||
31A47BA9156C210D0039B1C2 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */;
|
||||
|
|
@ -1152,6 +1170,15 @@
|
|||
);
|
||||
runOnlyForDeploymentPostprocessing = 1;
|
||||
};
|
||||
31108A421C6B90E900E728EA /* CopyFiles */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = /usr/share/man/man1/;
|
||||
dstSubfolderSpec = 0;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 1;
|
||||
};
|
||||
3114A58E156E913C001E0AA3 /* CopyFiles */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
|
|
@ -1471,6 +1498,8 @@
|
|||
3107DC4E173B03D100F705C8 /* arg.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = arg.h; sourceTree = "<group>"; };
|
||||
310F5D7118B6675F007EFCBC /* tree.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = tree.c; sourceTree = "<group>"; };
|
||||
310F5D7218B6675F007EFCBC /* tree.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = tree.h; sourceTree = "<group>"; };
|
||||
31108A391C6B90D600E728EA /* tagtest.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = tagtest.c; sourceTree = "<group>"; };
|
||||
31108A471C6B90E900E728EA /* tagtest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = tagtest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
3112ED3A18ABC57F00CC531A /* sa.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = sa.h; sourceTree = "<group>"; };
|
||||
3112ED3B18ABC75200CC531A /* sa.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = sa.c; sourceTree = "<group>"; };
|
||||
3114A590156E913C001E0AA3 /* locv */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = locv; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
|
|
@ -1540,7 +1569,6 @@
|
|||
31160DB61899540D0071EB17 /* poolmvff.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = poolmvff.txt; path = ../design/poolmvff.txt; sourceTree = "<group>"; };
|
||||
31160DB71899540D0071EB17 /* poolmvt.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = poolmvt.txt; path = ../design/poolmvt.txt; sourceTree = "<group>"; };
|
||||
31160DB81899540D0071EB17 /* prot.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = prot.txt; path = ../design/prot.txt; sourceTree = "<group>"; };
|
||||
31160DB91899540D0071EB17 /* protan.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = protan.txt; path = ../design/protan.txt; sourceTree = "<group>"; };
|
||||
31160DBA1899540D0071EB17 /* protli.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = protli.txt; path = ../design/protli.txt; sourceTree = "<group>"; };
|
||||
31160DBB1899540D0071EB17 /* protocol.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = protocol.txt; path = ../design/protocol.txt; sourceTree = "<group>"; };
|
||||
31160DBC1899540D0071EB17 /* protsu.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = protsu.txt; path = ../design/protsu.txt; sourceTree = "<group>"; };
|
||||
|
|
@ -1565,7 +1593,6 @@
|
|||
31160DCF1899540D0071EB17 /* version-library.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = "version-library.txt"; path = "../design/version-library.txt"; sourceTree = "<group>"; };
|
||||
31160DD01899540D0071EB17 /* version.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = version.txt; path = ../design/version.txt; sourceTree = "<group>"; };
|
||||
31160DD11899540D0071EB17 /* vm.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = vm.txt; path = ../design/vm.txt; sourceTree = "<group>"; };
|
||||
31160DD21899540D0071EB17 /* vman.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = vman.txt; path = ../design/vman.txt; sourceTree = "<group>"; };
|
||||
31160DD31899540D0071EB17 /* vmo1.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = vmo1.txt; path = ../design/vmo1.txt; sourceTree = "<group>"; };
|
||||
31160DD41899540D0071EB17 /* vmso.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = vmso.txt; path = ../design/vmso.txt; sourceTree = "<group>"; };
|
||||
31160DD51899540D0071EB17 /* writef.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = writef.txt; path = ../design/writef.txt; sourceTree = "<group>"; };
|
||||
|
|
@ -1577,7 +1604,6 @@
|
|||
311F2F5017398AD500C15B6A /* boot.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = boot.h; sourceTree = "<group>"; };
|
||||
311F2F5117398AE900C15B6A /* bt.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = bt.h; sourceTree = "<group>"; };
|
||||
311F2F5217398AE900C15B6A /* cbs.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = cbs.h; sourceTree = "<group>"; };
|
||||
311F2F5317398AE900C15B6A /* chain.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = chain.h; sourceTree = "<group>"; };
|
||||
311F2F5417398AE900C15B6A /* check.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = check.h; sourceTree = "<group>"; };
|
||||
311F2F5517398AE900C15B6A /* clock.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = clock.h; sourceTree = "<group>"; };
|
||||
311F2F5617398AE900C15B6A /* config.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = config.h; sourceTree = "<group>"; };
|
||||
|
|
@ -1586,7 +1612,6 @@
|
|||
311F2F5917398AE900C15B6A /* eventcom.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = eventcom.h; sourceTree = "<group>"; };
|
||||
311F2F5A17398AE900C15B6A /* eventdef.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = eventdef.h; sourceTree = "<group>"; };
|
||||
311F2F5C17398AE900C15B6A /* eventrep.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = eventrep.h; sourceTree = "<group>"; };
|
||||
311F2F5D17398B0400C15B6A /* lo.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = lo.h; sourceTree = "<group>"; };
|
||||
311F2F5E17398B0E00C15B6A /* lock.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = lock.h; sourceTree = "<group>"; };
|
||||
311F2F5F17398B0E00C15B6A /* meter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = meter.h; sourceTree = "<group>"; };
|
||||
311F2F6017398B0E00C15B6A /* misc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = misc.h; sourceTree = "<group>"; };
|
||||
|
|
@ -1628,11 +1653,62 @@
|
|||
3124CAE4156BE6D500753214 /* fmthe.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fmthe.c; sourceTree = "<group>"; };
|
||||
3124CAEB156BE7F300753214 /* amcss */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = amcss; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
3124CAF5156BE81100753214 /* amcss.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = amcss.c; sourceTree = "<group>"; };
|
||||
314562191C72ABFA00D7A514 /* scan.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = scan.c; sourceTree = "<group>"; };
|
||||
315B7AFC17834FDB00B097C4 /* proti3.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = proti3.c; sourceTree = "<group>"; };
|
||||
315B7AFD17834FDB00B097C4 /* proti6.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = proti6.c; sourceTree = "<group>"; };
|
||||
317B3C2A1731830100F9A469 /* arg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = arg.c; sourceTree = "<group>"; };
|
||||
318DA8CD1892B0F30089718C /* djbench */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = djbench; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
318DA8CE1892B1210089718C /* djbench.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = djbench.c; sourceTree = "<group>"; };
|
||||
31942A671C8EC3FC001AAF32 /* locus.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = locus.h; sourceTree = "<group>"; };
|
||||
31942A681C8EC445001AAF32 /* abq.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = abq.txt; path = ../design/abq.txt; sourceTree = "<group>"; };
|
||||
31942A6A1C8EC445001AAF32 /* an.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = an.txt; path = ../design/an.txt; sourceTree = "<group>"; };
|
||||
31942A6B1C8EC445001AAF32 /* arena.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = arena.txt; path = ../design/arena.txt; sourceTree = "<group>"; };
|
||||
31942A6D1C8EC445001AAF32 /* boot.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = boot.txt; path = ../design/boot.txt; sourceTree = "<group>"; };
|
||||
31942A6E1C8EC445001AAF32 /* bootstrap.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = bootstrap.txt; path = ../design/bootstrap.txt; sourceTree = "<group>"; };
|
||||
31942A6F1C8EC445001AAF32 /* bt.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = bt.txt; path = ../design/bt.txt; sourceTree = "<group>"; };
|
||||
31942A711C8EC445001AAF32 /* cbs.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = cbs.txt; path = ../design/cbs.txt; sourceTree = "<group>"; };
|
||||
31942A731C8EC445001AAF32 /* class-interface.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = "class-interface.txt"; path = "../design/class-interface.txt"; sourceTree = "<group>"; };
|
||||
31942A741C8EC445001AAF32 /* clock.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = clock.txt; path = ../design/clock.txt; sourceTree = "<group>"; };
|
||||
31942A761C8EC445001AAF32 /* config.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = config.txt; path = ../design/config.txt; sourceTree = "<group>"; };
|
||||
31942A781C8EC445001AAF32 /* diag.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = diag.txt; path = ../design/diag.txt; sourceTree = "<group>"; };
|
||||
31942A791C8EC445001AAF32 /* exec-env.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = "exec-env.txt"; path = "../design/exec-env.txt"; sourceTree = "<group>"; };
|
||||
31942A7B1C8EC445001AAF32 /* finalize.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = finalize.txt; path = ../design/finalize.txt; sourceTree = "<group>"; };
|
||||
31942A7D1C8EC445001AAF32 /* freelist.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = freelist.txt; path = ../design/freelist.txt; sourceTree = "<group>"; };
|
||||
31942A7F1C8EC445001AAF32 /* guide.impl.c.format.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = guide.impl.c.format.txt; path = ../design/guide.impl.c.format.txt; sourceTree = "<group>"; };
|
||||
31942A801C8EC445001AAF32 /* guide.impl.c.naming.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = guide.impl.c.naming.txt; path = ../design/guide.impl.c.naming.txt; sourceTree = "<group>"; };
|
||||
31942A811C8EC445001AAF32 /* guide.review.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = guide.review.txt; path = ../design/guide.review.txt; sourceTree = "<group>"; };
|
||||
31942A831C8EC445001AAF32 /* interface-c.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = "interface-c.txt"; path = "../design/interface-c.txt"; sourceTree = "<group>"; };
|
||||
31942A851C8EC445001AAF32 /* keyword-arguments.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = "keyword-arguments.txt"; path = "../design/keyword-arguments.txt"; sourceTree = "<group>"; };
|
||||
31942A871C8EC445001AAF32 /* lib.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = lib.txt; path = ../design/lib.txt; sourceTree = "<group>"; };
|
||||
31942A891C8EC445001AAF32 /* locus.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = locus.txt; path = ../design/locus.txt; sourceTree = "<group>"; };
|
||||
31942A8B1C8EC446001AAF32 /* message.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = message.txt; path = ../design/message.txt; sourceTree = "<group>"; };
|
||||
31942A8C1C8EC446001AAF32 /* nailboard-1.svg */ = {isa = PBXFileReference; lastKnownFileType = text.xml; name = "nailboard-1.svg"; path = "../design/nailboard-1.svg"; sourceTree = "<group>"; };
|
||||
31942A8D1C8EC446001AAF32 /* nailboard-2.svg */ = {isa = PBXFileReference; lastKnownFileType = text.xml; name = "nailboard-2.svg"; path = "../design/nailboard-2.svg"; sourceTree = "<group>"; };
|
||||
31942A8E1C8EC446001AAF32 /* nailboard-3.svg */ = {isa = PBXFileReference; lastKnownFileType = text.xml; name = "nailboard-3.svg"; path = "../design/nailboard-3.svg"; sourceTree = "<group>"; };
|
||||
31942A8F1C8EC446001AAF32 /* nailboard.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = nailboard.txt; path = ../design/nailboard.txt; sourceTree = "<group>"; };
|
||||
31942A911C8EC446001AAF32 /* pool.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = pool.txt; path = ../design/pool.txt; sourceTree = "<group>"; };
|
||||
31942A931C8EC446001AAF32 /* poolams.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = poolams.txt; path = ../design/poolams.txt; sourceTree = "<group>"; };
|
||||
31942A951C8EC446001AAF32 /* poollo.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = poollo.txt; path = ../design/poollo.txt; sourceTree = "<group>"; };
|
||||
31942A971C8EC446001AAF32 /* poolmrg.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = poolmrg.txt; path = ../design/poolmrg.txt; sourceTree = "<group>"; };
|
||||
31942A991C8EC446001AAF32 /* poolmvff.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = poolmvff.txt; path = ../design/poolmvff.txt; sourceTree = "<group>"; };
|
||||
31942A9B1C8EC446001AAF32 /* prmc.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = prmc.txt; path = ../design/prmc.txt; sourceTree = "<group>"; };
|
||||
31942A9C1C8EC446001AAF32 /* prot.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = prot.txt; path = ../design/prot.txt; sourceTree = "<group>"; };
|
||||
31942A9E1C8EC446001AAF32 /* protocol.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = protocol.txt; path = ../design/protocol.txt; sourceTree = "<group>"; };
|
||||
31942AA01C8EC446001AAF32 /* pthreadext.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = pthreadext.txt; path = ../design/pthreadext.txt; sourceTree = "<group>"; };
|
||||
31942AA21C8EC446001AAF32 /* reservoir.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = reservoir.txt; path = ../design/reservoir.txt; sourceTree = "<group>"; };
|
||||
31942AA41C8EC446001AAF32 /* root.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = root.txt; path = ../design/root.txt; sourceTree = "<group>"; };
|
||||
31942AA61C8EC446001AAF32 /* seg.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = seg.txt; path = ../design/seg.txt; sourceTree = "<group>"; };
|
||||
31942AA81C8EC446001AAF32 /* sig.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = sig.txt; path = ../design/sig.txt; sourceTree = "<group>"; };
|
||||
31942AA91C8EC446001AAF32 /* sp.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = sp.txt; path = ../design/sp.txt; sourceTree = "<group>"; };
|
||||
31942AAB1C8EC446001AAF32 /* ss.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = ss.txt; path = ../design/ss.txt; sourceTree = "<group>"; };
|
||||
31942AAC1C8EC446001AAF32 /* sso1al.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = sso1al.txt; path = ../design/sso1al.txt; sourceTree = "<group>"; };
|
||||
31942AAE1C8EC446001AAF32 /* telemetry.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = telemetry.txt; path = ../design/telemetry.txt; sourceTree = "<group>"; };
|
||||
31942AB01C8EC446001AAF32 /* testthr.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = testthr.txt; path = ../design/testthr.txt; sourceTree = "<group>"; };
|
||||
31942AB11C8EC446001AAF32 /* thread-manager.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = "thread-manager.txt"; path = "../design/thread-manager.txt"; sourceTree = "<group>"; };
|
||||
31942AB31C8EC446001AAF32 /* trace.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = trace.txt; path = ../design/trace.txt; sourceTree = "<group>"; };
|
||||
31942AB51C8EC446001AAF32 /* version-library.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = "version-library.txt"; path = "../design/version-library.txt"; sourceTree = "<group>"; };
|
||||
31942AB71C8EC446001AAF32 /* vm.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = vm.txt; path = ../design/vm.txt; sourceTree = "<group>"; };
|
||||
31942AB91C8EC446001AAF32 /* vmso.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = vmso.txt; path = ../design/vmso.txt; sourceTree = "<group>"; };
|
||||
31A47BA3156C1E130039B1C2 /* mps.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mps.c; sourceTree = "<group>"; };
|
||||
31A47BA5156C1E5E0039B1C2 /* ssixi3.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = ssixi3.c; sourceTree = "<group>"; };
|
||||
31C83ADD1786281C0031A0DB /* protxc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = protxc.h; sourceTree = "<group>"; };
|
||||
|
|
@ -1866,6 +1942,14 @@
|
|||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
31108A401C6B90E900E728EA /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
31108A411C6B90E900E728EA /* libmps.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
3114A58D156E913C001E0AA3 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
|
|
@ -2126,7 +2210,90 @@
|
|||
31160D90189953D50071EB17 /* Design */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
31942A681C8EC445001AAF32 /* abq.txt */,
|
||||
31160D931899540D0071EB17 /* alloc-frame.txt */,
|
||||
31942A6A1C8EC445001AAF32 /* an.txt */,
|
||||
31942A6B1C8EC445001AAF32 /* arena.txt */,
|
||||
31160D951899540D0071EB17 /* arenavm.txt */,
|
||||
31942A6D1C8EC445001AAF32 /* boot.txt */,
|
||||
31942A6E1C8EC445001AAF32 /* bootstrap.txt */,
|
||||
31942A6F1C8EC445001AAF32 /* bt.txt */,
|
||||
31160D971899540D0071EB17 /* buffer.txt */,
|
||||
31942A711C8EC445001AAF32 /* cbs.txt */,
|
||||
31160D991899540D0071EB17 /* check.txt */,
|
||||
31942A731C8EC445001AAF32 /* class-interface.txt */,
|
||||
31942A741C8EC445001AAF32 /* clock.txt */,
|
||||
31160D9B1899540D0071EB17 /* collection.txt */,
|
||||
31942A761C8EC445001AAF32 /* config.txt */,
|
||||
31160D9D1899540D0071EB17 /* critical-path.txt */,
|
||||
31942A781C8EC445001AAF32 /* diag.txt */,
|
||||
31942A791C8EC445001AAF32 /* exec-env.txt */,
|
||||
22DD93E118ED815F00240DD2 /* failover.txt */,
|
||||
31942A7B1C8EC445001AAF32 /* finalize.txt */,
|
||||
31160DA01899540D0071EB17 /* fix.txt */,
|
||||
31942A7D1C8EC445001AAF32 /* freelist.txt */,
|
||||
31160DA21899540D0071EB17 /* guide.hex.trans.txt */,
|
||||
31942A7F1C8EC445001AAF32 /* guide.impl.c.format.txt */,
|
||||
31942A801C8EC445001AAF32 /* guide.impl.c.naming.txt */,
|
||||
31942A811C8EC445001AAF32 /* guide.review.txt */,
|
||||
31160DA41899540D0071EB17 /* index.txt */,
|
||||
31942A831C8EC445001AAF32 /* interface-c.txt */,
|
||||
31160DA61899540D0071EB17 /* io.txt */,
|
||||
31942A851C8EC445001AAF32 /* keyword-arguments.txt */,
|
||||
22DD93E218ED815F00240DD2 /* land.txt */,
|
||||
31942A871C8EC445001AAF32 /* lib.txt */,
|
||||
31160DA91899540D0071EB17 /* lock.txt */,
|
||||
31942A891C8EC445001AAF32 /* locus.txt */,
|
||||
31160DAB1899540D0071EB17 /* message-gc.txt */,
|
||||
31942A8B1C8EC446001AAF32 /* message.txt */,
|
||||
31942A8C1C8EC446001AAF32 /* nailboard-1.svg */,
|
||||
31942A8D1C8EC446001AAF32 /* nailboard-2.svg */,
|
||||
31942A8E1C8EC446001AAF32 /* nailboard-3.svg */,
|
||||
31942A8F1C8EC446001AAF32 /* nailboard.txt */,
|
||||
31160DAD1899540D0071EB17 /* object-debug.txt */,
|
||||
31942A911C8EC446001AAF32 /* pool.txt */,
|
||||
31160DAF1899540D0071EB17 /* poolamc.txt */,
|
||||
31942A931C8EC446001AAF32 /* poolams.txt */,
|
||||
31160DB11899540D0071EB17 /* poolawl.txt */,
|
||||
31942A951C8EC446001AAF32 /* poollo.txt */,
|
||||
31160DB31899540D0071EB17 /* poolmfs.txt */,
|
||||
31942A971C8EC446001AAF32 /* poolmrg.txt */,
|
||||
31160DB51899540D0071EB17 /* poolmv.txt */,
|
||||
31942A991C8EC446001AAF32 /* poolmvff.txt */,
|
||||
31160DB71899540D0071EB17 /* poolmvt.txt */,
|
||||
31942A9B1C8EC446001AAF32 /* prmc.txt */,
|
||||
31942A9C1C8EC446001AAF32 /* prot.txt */,
|
||||
31160DBA1899540D0071EB17 /* protli.txt */,
|
||||
31942A9E1C8EC446001AAF32 /* protocol.txt */,
|
||||
31160DBC1899540D0071EB17 /* protsu.txt */,
|
||||
31942AA01C8EC446001AAF32 /* pthreadext.txt */,
|
||||
31160DBE1899540D0071EB17 /* range.txt */,
|
||||
31942AA21C8EC446001AAF32 /* reservoir.txt */,
|
||||
31160DC01899540D0071EB17 /* ring.txt */,
|
||||
31942AA41C8EC446001AAF32 /* root.txt */,
|
||||
31160DC21899540D0071EB17 /* scan.txt */,
|
||||
31942AA61C8EC446001AAF32 /* seg.txt */,
|
||||
31160DC41899540D0071EB17 /* shield.txt */,
|
||||
31942AA81C8EC446001AAF32 /* sig.txt */,
|
||||
31942AA91C8EC446001AAF32 /* sp.txt */,
|
||||
31160DC61899540D0071EB17 /* splay.txt */,
|
||||
31942AAB1C8EC446001AAF32 /* ss.txt */,
|
||||
31942AAC1C8EC446001AAF32 /* sso1al.txt */,
|
||||
31160DC81899540D0071EB17 /* strategy.txt */,
|
||||
31942AAE1C8EC446001AAF32 /* telemetry.txt */,
|
||||
31160DCA1899540D0071EB17 /* tests.txt */,
|
||||
31942AB01C8EC446001AAF32 /* testthr.txt */,
|
||||
31942AB11C8EC446001AAF32 /* thread-manager.txt */,
|
||||
31160DCC1899540D0071EB17 /* thread-safety.txt */,
|
||||
31942AB31C8EC446001AAF32 /* trace.txt */,
|
||||
31160DCE1899540D0071EB17 /* type.txt */,
|
||||
31942AB51C8EC446001AAF32 /* version-library.txt */,
|
||||
31160DD01899540D0071EB17 /* version.txt */,
|
||||
31942AB71C8EC446001AAF32 /* vm.txt */,
|
||||
31160DD31899540D0071EB17 /* vmo1.txt */,
|
||||
31942AB91C8EC446001AAF32 /* vmso.txt */,
|
||||
31160D921899540D0071EB17 /* abq.txt */,
|
||||
31160DD51899540D0071EB17 /* writef.txt */,
|
||||
31160D931899540D0071EB17 /* alloc-frame.txt */,
|
||||
31160D941899540D0071EB17 /* arena.txt */,
|
||||
31160D951899540D0071EB17 /* arenavm.txt */,
|
||||
|
|
@ -2167,7 +2334,6 @@
|
|||
31160DB61899540D0071EB17 /* poolmvff.txt */,
|
||||
31160DB71899540D0071EB17 /* poolmvt.txt */,
|
||||
31160DB81899540D0071EB17 /* prot.txt */,
|
||||
31160DB91899540D0071EB17 /* protan.txt */,
|
||||
31160DBA1899540D0071EB17 /* protli.txt */,
|
||||
31160DBB1899540D0071EB17 /* protocol.txt */,
|
||||
31160DBC1899540D0071EB17 /* protsu.txt */,
|
||||
|
|
@ -2192,7 +2358,6 @@
|
|||
31160DCF1899540D0071EB17 /* version-library.txt */,
|
||||
31160DD01899540D0071EB17 /* version.txt */,
|
||||
31160DD11899540D0071EB17 /* vm.txt */,
|
||||
31160DD21899540D0071EB17 /* vman.txt */,
|
||||
31160DD31899540D0071EB17 /* vmo1.txt */,
|
||||
31160DD41899540D0071EB17 /* vmso.txt */,
|
||||
31160DD51899540D0071EB17 /* writef.txt */,
|
||||
|
|
@ -2248,6 +2413,7 @@
|
|||
3104AFD6156D3602000A585A /* sacss.c */,
|
||||
31D60006156D3C5F00337B26 /* segsmss.c */,
|
||||
31D60098156D403C00337B26 /* steptest.c */,
|
||||
31108A391C6B90D600E728EA /* tagtest.c */,
|
||||
3114A628156E949A001E0AA3 /* teletest.c */,
|
||||
31EEAC9E156AB73400714D05 /* testlib.c */,
|
||||
2291A5F0175CB7A4001D4920 /* testlib.h */,
|
||||
|
|
@ -2345,6 +2511,7 @@
|
|||
22FACEED18880983000FDBC1 /* airtest */,
|
||||
22C2ACAF18BE400A006B3677 /* nailboardtest */,
|
||||
22F846BD18F437B900982BA7 /* lockut */,
|
||||
31108A471C6B90E900E728EA /* tagtest */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -2352,6 +2519,7 @@
|
|||
31EEABF4156AAF6500714D05 /* MPM Core */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
31942A671C8EC3FC001AAF32 /* locus.h */,
|
||||
3114A645156E9525001E0AA3 /* abq.c */,
|
||||
2291A5EA175CB503001D4920 /* abq.h */,
|
||||
31EEAC05156AB27B00714D05 /* arena.c */,
|
||||
|
|
@ -2366,7 +2534,6 @@
|
|||
31EEAC19156AB2B200714D05 /* buffer.c */,
|
||||
31EEAC40156AB32500714D05 /* cbs.c */,
|
||||
311F2F5217398AE900C15B6A /* cbs.h */,
|
||||
311F2F5317398AE900C15B6A /* chain.h */,
|
||||
311F2F5417398AE900C15B6A /* check.h */,
|
||||
311F2F5517398AE900C15B6A /* clock.h */,
|
||||
311F2F5617398AE900C15B6A /* config.h */,
|
||||
|
|
@ -2437,6 +2604,7 @@
|
|||
31EEAC31156AB2F200714D05 /* sac.c */,
|
||||
311F2F7417398B7100C15B6A /* sac.h */,
|
||||
311F2F7517398B8E00C15B6A /* sc.h */,
|
||||
314562191C72ABFA00D7A514 /* scan.c */,
|
||||
31EEAC1D156AB2B200714D05 /* seg.c */,
|
||||
31EEAC32156AB2F200714D05 /* shield.c */,
|
||||
31EEAC43156AB32500714D05 /* splay.c */,
|
||||
|
|
@ -2483,7 +2651,6 @@
|
|||
31EEAC5A156AB40800714D05 /* Extra pools */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
311F2F5D17398B0400C15B6A /* lo.h */,
|
||||
31F6CCA91739B0CF00C48748 /* mpscamc.h */,
|
||||
31CD33BB173A9F1500524741 /* mpscams.h */,
|
||||
31F6CCAA1739B0CF00C48748 /* mpscawl.h */,
|
||||
|
|
@ -2873,6 +3040,24 @@
|
|||
productReference = 3104B03D156D3AD7000A585A /* segsmss */;
|
||||
productType = "com.apple.product-type.tool";
|
||||
};
|
||||
31108A3A1C6B90E900E728EA /* tagtest */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 31108A431C6B90E900E728EA /* Build configuration list for PBXNativeTarget "tagtest" */;
|
||||
buildPhases = (
|
||||
31108A3D1C6B90E900E728EA /* Sources */,
|
||||
31108A401C6B90E900E728EA /* Frameworks */,
|
||||
31108A421C6B90E900E728EA /* CopyFiles */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
31108A3B1C6B90E900E728EA /* PBXTargetDependency */,
|
||||
);
|
||||
name = tagtest;
|
||||
productName = teletest;
|
||||
productReference = 31108A471C6B90E900E728EA /* tagtest */;
|
||||
productType = "com.apple.product-type.tool";
|
||||
};
|
||||
3114A58F156E913C001E0AA3 /* locv */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 3114A599156E913C001E0AA3 /* Build configuration list for PBXNativeTarget "locv" */;
|
||||
|
|
@ -3446,6 +3631,7 @@
|
|||
2D604B9B16514B1A003AAF46 /* mpseventtxt */,
|
||||
31FCAE0917692403008C034C /* scheme */,
|
||||
22B2BC2C18B6434F00C33E63 /* scheme-advanced */,
|
||||
31108A3A1C6B90E900E728EA /* tagtest */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
|
@ -3725,6 +3911,15 @@
|
|||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
31108A3D1C6B90E900E728EA /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
31108A3E1C6B90E900E728EA /* testlib.c in Sources */,
|
||||
31108A481C6B911B00E728EA /* tagtest.c in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
3114A58C156E913C001E0AA3 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
|
|
@ -4258,6 +4453,11 @@
|
|||
target = 3104B03C156D3AD7000A585A /* segsmss */;
|
||||
targetProxy = 3104B049156D3AE4000A585A /* PBXContainerItemProxy */;
|
||||
};
|
||||
31108A3B1C6B90E900E728EA /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 31EEABFA156AAF9D00714D05 /* mps */;
|
||||
targetProxy = 31108A3C1C6B90E900E728EA /* PBXContainerItemProxy */;
|
||||
};
|
||||
3114A59E156E9156001E0AA3 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 31EEABFA156AAF9D00714D05 /* mps */;
|
||||
|
|
@ -4398,6 +4598,11 @@
|
|||
target = 3114A6C5156E9815001E0AA3 /* mpseventcnv */;
|
||||
targetProxy = 3114A6D4156E9839001E0AA3 /* PBXContainerItemProxy */;
|
||||
};
|
||||
314CB6EB1C6D272A0073CA42 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 31108A3A1C6B90E900E728EA /* tagtest */;
|
||||
targetProxy = 314CB6EA1C6D272A0073CA42 /* PBXContainerItemProxy */;
|
||||
};
|
||||
31A47BAA156C210D0039B1C2 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 31EEABFA156AAF9D00714D05 /* mps */;
|
||||
|
|
@ -4903,6 +5108,27 @@
|
|||
};
|
||||
name = Release;
|
||||
};
|
||||
31108A441C6B90E900E728EA /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
31108A451C6B90E900E728EA /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
31108A461C6B90E900E728EA /* RASH */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = RASH;
|
||||
};
|
||||
3114A597156E913C001E0AA3 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
|
|
@ -5191,21 +5417,7 @@
|
|||
SDKROOT = macosx;
|
||||
SYMROOT = xc;
|
||||
WARNING_CFLAGS = (
|
||||
"-pedantic",
|
||||
"-Waggregate-return",
|
||||
"-Wall",
|
||||
"-Wcast-qual",
|
||||
"-Wextra",
|
||||
"-Winline",
|
||||
"-Wmissing-prototypes",
|
||||
"-Wnested-externs",
|
||||
"-Wno-extended-offsetof",
|
||||
"-Wpointer-arith",
|
||||
"-Wshadow",
|
||||
"-Wstrict-aliasing=2",
|
||||
"-Wstrict-prototypes",
|
||||
"-Wunreachable-code",
|
||||
"-Wwrite-strings",
|
||||
"-pedantic\n-Waggregate-return\n-Wall\n-Wcast-qual\n-Wconversion\n-Wduplicate-enum\n-Wextra\n-Winline\n-Wmissing-prototypes\n-Wmissing-variable-declarations\n-Wnested-externs\n-Wno-extended-offsetof\n-Wpointer-arith\n-Wshadow\n-Wstrict-aliasing=2\n-Wstrict-prototypes\n-Wunreachable-code\n-Wwrite-strings\n",
|
||||
);
|
||||
};
|
||||
name = RASH;
|
||||
|
|
@ -5628,21 +5840,7 @@
|
|||
SDKROOT = macosx;
|
||||
SYMROOT = xc;
|
||||
WARNING_CFLAGS = (
|
||||
"-pedantic",
|
||||
"-Waggregate-return",
|
||||
"-Wall",
|
||||
"-Wcast-qual",
|
||||
"-Wextra",
|
||||
"-Winline",
|
||||
"-Wmissing-prototypes",
|
||||
"-Wnested-externs",
|
||||
"-Wno-extended-offsetof",
|
||||
"-Wpointer-arith",
|
||||
"-Wshadow",
|
||||
"-Wstrict-aliasing=2",
|
||||
"-Wstrict-prototypes",
|
||||
"-Wunreachable-code",
|
||||
"-Wwrite-strings",
|
||||
"-pedantic\n-Waggregate-return\n-Wall\n-Wcast-qual\n-Wconversion\n-Wduplicate-enum\n-Wextra\n-Winline\n-Wmissing-prototypes\n-Wmissing-variable-declarations\n-Wnested-externs\n-Wno-extended-offsetof\n-Wpointer-arith\n-Wshadow\n-Wstrict-aliasing=2\n-Wstrict-prototypes\n-Wunreachable-code\n-Wwrite-strings\n",
|
||||
);
|
||||
};
|
||||
name = Debug;
|
||||
|
|
@ -5683,21 +5881,7 @@
|
|||
SDKROOT = macosx;
|
||||
SYMROOT = xc;
|
||||
WARNING_CFLAGS = (
|
||||
"-pedantic",
|
||||
"-Waggregate-return",
|
||||
"-Wall",
|
||||
"-Wcast-qual",
|
||||
"-Wextra",
|
||||
"-Winline",
|
||||
"-Wmissing-prototypes",
|
||||
"-Wnested-externs",
|
||||
"-Wno-extended-offsetof",
|
||||
"-Wpointer-arith",
|
||||
"-Wshadow",
|
||||
"-Wstrict-aliasing=2",
|
||||
"-Wstrict-prototypes",
|
||||
"-Wunreachable-code",
|
||||
"-Wwrite-strings",
|
||||
"-pedantic\n-Waggregate-return\n-Wall\n-Wcast-qual\n-Wconversion\n-Wduplicate-enum\n-Wextra\n-Winline\n-Wmissing-prototypes\n-Wmissing-variable-declarations\n-Wnested-externs\n-Wno-extended-offsetof\n-Wpointer-arith\n-Wshadow\n-Wstrict-aliasing=2\n-Wstrict-prototypes\n-Wunreachable-code\n-Wwrite-strings\n",
|
||||
);
|
||||
};
|
||||
name = Release;
|
||||
|
|
@ -6022,6 +6206,16 @@
|
|||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
31108A431C6B90E900E728EA /* Build configuration list for PBXNativeTarget "tagtest" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
31108A441C6B90E900E728EA /* Debug */,
|
||||
31108A451C6B90E900E728EA /* Release */,
|
||||
31108A461C6B90E900E728EA /* RASH */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
3114A599156E913C001E0AA3 /* Build configuration list for PBXNativeTarget "locv" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
|
|
|
|||
212
mps/code/mpsi.c
212
mps/code/mpsi.c
|
|
@ -40,13 +40,9 @@
|
|||
* present. This is because the MPM doesn't ever try to protect them.
|
||||
* In future, it will.
|
||||
*
|
||||
* .reg-scan: (rule.universal.complete) At present, we only support
|
||||
* register scanning using our own ambiguous register and stack scanning
|
||||
* method, mps_stack_scan_ambig. This may never change, but the way the
|
||||
* interface is designed allows for the possibility of change.
|
||||
*
|
||||
* .naming: (rule.impl.guide) The exported identifiers do not follow the
|
||||
* normal MPS naming conventions. See <design/interface-c/#naming>. */
|
||||
* normal MPS naming conventions. See <design/interface-c/#naming>.
|
||||
*/
|
||||
|
||||
#include "mpm.h"
|
||||
#include "mps.h"
|
||||
|
|
@ -1299,12 +1295,14 @@ mps_res_t mps_root_create_table(mps_root_t *mps_root_o, mps_arena_t arena,
|
|||
AVER(base != NULL);
|
||||
AVER(size > 0);
|
||||
|
||||
/* .root.table-size: size is the length of the array at base, not */
|
||||
/* the size in bytes. However, RootCreateTable expects base and */
|
||||
/* limit pointers. Be careful. */
|
||||
/* .root.table-size: size is the length of the array at base, not
|
||||
the size in bytes. However, RootCreateArea expects base and limit
|
||||
pointers. Be careful. Avoid type punning by casting through
|
||||
void *. */
|
||||
|
||||
res = RootCreateTable(&root, arena, rank, mode,
|
||||
(Addr *)base, (Addr *)base + size);
|
||||
res = RootCreateArea(&root, arena, rank, mode,
|
||||
(void *)base, (void *)(base + size),
|
||||
mps_scan_area, NULL);
|
||||
|
||||
ArenaLeave(arena);
|
||||
|
||||
|
|
@ -1314,11 +1312,12 @@ mps_res_t mps_root_create_table(mps_root_t *mps_root_o, mps_arena_t arena,
|
|||
return MPS_RES_OK;
|
||||
}
|
||||
|
||||
mps_res_t mps_root_create_table_masked(mps_root_t *mps_root_o,
|
||||
mps_res_t mps_root_create_area(mps_root_t *mps_root_o,
|
||||
mps_arena_t arena,
|
||||
mps_rank_t mps_rank, mps_rm_t mps_rm,
|
||||
mps_addr_t *base, size_t size,
|
||||
mps_word_t mask)
|
||||
void *base, void *limit,
|
||||
mps_area_scan_t scan_area,
|
||||
void *closure)
|
||||
{
|
||||
Rank rank = (Rank)mps_rank;
|
||||
Root root;
|
||||
|
|
@ -1329,14 +1328,14 @@ mps_res_t mps_root_create_table_masked(mps_root_t *mps_root_o,
|
|||
|
||||
AVER(mps_root_o != NULL);
|
||||
AVER(base != NULL);
|
||||
AVER(size > 0);
|
||||
/* Can't check anything about mask */
|
||||
AVER(limit != NULL);
|
||||
AVER(base < limit);
|
||||
AVER(FUNCHECK(scan_area));
|
||||
/* Can't check anything about closure */
|
||||
|
||||
/* See .root.table-size. */
|
||||
|
||||
res = RootCreateTableMasked(&root, arena, rank, mode,
|
||||
(Addr *)base, (Addr *)base + size,
|
||||
mask);
|
||||
res = RootCreateArea(&root, arena, rank, mode,
|
||||
base, limit,
|
||||
scan_area, closure);
|
||||
|
||||
ArenaLeave(arena);
|
||||
|
||||
|
|
@ -1346,6 +1345,56 @@ mps_res_t mps_root_create_table_masked(mps_root_t *mps_root_o,
|
|||
return MPS_RES_OK;
|
||||
}
|
||||
|
||||
mps_res_t mps_root_create_area_tagged(mps_root_t *mps_root_o,
|
||||
mps_arena_t arena,
|
||||
mps_rank_t mps_rank,
|
||||
mps_rm_t mps_rm,
|
||||
void *base,
|
||||
void *limit,
|
||||
mps_area_scan_t scan_area,
|
||||
mps_word_t mask,
|
||||
mps_word_t pattern)
|
||||
{
|
||||
Rank rank = (Rank)mps_rank;
|
||||
Root root;
|
||||
RootMode mode = (RootMode)mps_rm;
|
||||
Res res;
|
||||
|
||||
ArenaEnter(arena);
|
||||
|
||||
AVER(mps_root_o != NULL);
|
||||
AVER(base != NULL);
|
||||
AVER(limit != NULL);
|
||||
AVER(base < limit);
|
||||
AVER(FUNCHECK(scan_area));
|
||||
/* Can't check anything about mask or pattern, as they could mean
|
||||
anything to scan_area. */
|
||||
|
||||
res = RootCreateAreaTagged(&root, arena, rank, mode,
|
||||
base, limit,
|
||||
scan_area, mask, pattern);
|
||||
|
||||
ArenaLeave(arena);
|
||||
|
||||
if (res != ResOK)
|
||||
return (mps_res_t)res;
|
||||
*mps_root_o = (mps_root_t)root;
|
||||
return MPS_RES_OK;
|
||||
}
|
||||
|
||||
|
||||
mps_res_t mps_root_create_table_masked(mps_root_t *mps_root_o,
|
||||
mps_arena_t arena,
|
||||
mps_rank_t mps_rank, mps_rm_t mps_rm,
|
||||
mps_addr_t *base, size_t size,
|
||||
mps_word_t mask)
|
||||
{
|
||||
return mps_root_create_area_tagged(mps_root_o, arena, mps_rank, mps_rm,
|
||||
base, base + size,
|
||||
mps_scan_area_tagged,
|
||||
mask, 0);
|
||||
}
|
||||
|
||||
mps_res_t mps_root_create_fmt(mps_root_t *mps_root_o, mps_arena_t arena,
|
||||
mps_rank_t mps_rank, mps_rm_t mps_rm,
|
||||
mps_fmt_scan_t scan,
|
||||
|
|
@ -1372,7 +1421,7 @@ mps_res_t mps_root_create_fmt(mps_root_t *mps_root_o, mps_arena_t arena,
|
|||
mps_res_t mps_root_create_reg(mps_root_t *mps_root_o, mps_arena_t arena,
|
||||
mps_rank_t mps_rank, mps_rm_t mps_rm,
|
||||
mps_thr_t thread, mps_reg_scan_t mps_reg_scan,
|
||||
void *reg_scan_p, size_t mps_size)
|
||||
void *cold, size_t mps_size)
|
||||
{
|
||||
Rank rank = (Rank)mps_rank;
|
||||
Root root;
|
||||
|
|
@ -1383,14 +1432,111 @@ mps_res_t mps_root_create_reg(mps_root_t *mps_root_o, mps_arena_t arena,
|
|||
AVER(mps_root_o != NULL);
|
||||
AVER(mps_reg_scan != NULL);
|
||||
AVER(mps_reg_scan == mps_stack_scan_ambig); /* .reg.scan */
|
||||
AVER(reg_scan_p != NULL); /* stackBot */
|
||||
AVER(AddrIsAligned(reg_scan_p, sizeof(Word)));
|
||||
AVER(cold != NULL);
|
||||
AVER(AddrIsAligned(cold, sizeof(Word)));
|
||||
AVER(rank == mps_rank_ambig());
|
||||
AVER(mps_rm == (mps_rm_t)0);
|
||||
|
||||
UNUSED(mps_size);
|
||||
|
||||
/* See .root-mode. */
|
||||
res = RootCreateReg(&root, arena, rank, thread,
|
||||
mps_reg_scan, reg_scan_p, mps_size);
|
||||
res = RootCreateThreadTagged(&root, arena, rank, thread,
|
||||
mps_scan_area_tagged,
|
||||
sizeof(mps_word_t) - 1, 0,
|
||||
(Word *)cold);
|
||||
|
||||
ArenaLeave(arena);
|
||||
|
||||
if (res != ResOK)
|
||||
return (mps_res_t)res;
|
||||
*mps_root_o = (mps_root_t)root;
|
||||
return MPS_RES_OK;
|
||||
}
|
||||
|
||||
|
||||
mps_res_t mps_root_create_thread(mps_root_t *mps_root_o,
|
||||
mps_arena_t arena,
|
||||
mps_thr_t thread,
|
||||
void *stack)
|
||||
{
|
||||
return mps_root_create_thread_tagged(mps_root_o,
|
||||
arena,
|
||||
mps_rank_ambig(),
|
||||
(mps_rm_t)0,
|
||||
thread,
|
||||
mps_scan_area_tagged,
|
||||
sizeof(mps_word_t) - 1,
|
||||
0,
|
||||
stack);
|
||||
}
|
||||
|
||||
|
||||
mps_res_t mps_root_create_thread_scanned(mps_root_t *mps_root_o,
|
||||
mps_arena_t arena,
|
||||
mps_rank_t mps_rank,
|
||||
mps_rm_t mps_rm,
|
||||
mps_thr_t thread,
|
||||
mps_area_scan_t scan_area,
|
||||
void *closure,
|
||||
void *cold)
|
||||
{
|
||||
Rank rank = (Rank)mps_rank;
|
||||
Root root;
|
||||
Res res;
|
||||
|
||||
ArenaEnter(arena);
|
||||
|
||||
AVER(mps_root_o != NULL);
|
||||
AVER(cold != NULL);
|
||||
AVER(AddrIsAligned(cold, sizeof(Word)));
|
||||
AVER(rank == mps_rank_ambig());
|
||||
AVER(mps_rm == (mps_rm_t)0);
|
||||
AVER(FUNCHECK(scan_area));
|
||||
/* Can't check anything about closure. */
|
||||
|
||||
/* See .root-mode. */
|
||||
res = RootCreateThread(&root, arena, rank, thread,
|
||||
scan_area, closure,
|
||||
(Word *)cold);
|
||||
|
||||
ArenaLeave(arena);
|
||||
|
||||
if (res != ResOK)
|
||||
return (mps_res_t)res;
|
||||
*mps_root_o = (mps_root_t)root;
|
||||
return MPS_RES_OK;
|
||||
}
|
||||
|
||||
|
||||
mps_res_t mps_root_create_thread_tagged(mps_root_t *mps_root_o,
|
||||
mps_arena_t arena,
|
||||
mps_rank_t mps_rank,
|
||||
mps_rm_t mps_rm,
|
||||
mps_thr_t thread,
|
||||
mps_area_scan_t scan_area,
|
||||
mps_word_t mask,
|
||||
mps_word_t pattern,
|
||||
void *cold)
|
||||
{
|
||||
Rank rank = (Rank)mps_rank;
|
||||
Root root;
|
||||
Res res;
|
||||
|
||||
ArenaEnter(arena);
|
||||
|
||||
AVER(mps_root_o != NULL);
|
||||
AVER(cold != NULL);
|
||||
AVER(AddrIsAligned(cold, sizeof(Word)));
|
||||
AVER(rank == mps_rank_ambig());
|
||||
AVER(mps_rm == (mps_rm_t)0);
|
||||
AVER(FUNCHECK(scan_area));
|
||||
/* Can't check anything about mask or pattern, as they could mean
|
||||
anything to scan_area. */
|
||||
|
||||
/* See .root-mode. */
|
||||
res = RootCreateThreadTagged(&root, arena, rank, thread,
|
||||
scan_area, mask, pattern,
|
||||
(Word *)cold);
|
||||
|
||||
ArenaLeave(arena);
|
||||
|
||||
|
|
@ -1403,14 +1549,22 @@ mps_res_t mps_root_create_reg(mps_root_t *mps_root_o, mps_arena_t arena,
|
|||
|
||||
/* mps_stack_scan_ambig -- scan the thread state ambiguously
|
||||
*
|
||||
* See .reg-scan. */
|
||||
* This is a helper function for the deprecated mps_root_create_reg
|
||||
* and should no longer be reached since that has been reimplemented
|
||||
* in terms of the more general RootCreateThreadTagged.
|
||||
*/
|
||||
|
||||
mps_res_t mps_stack_scan_ambig(mps_ss_t mps_ss,
|
||||
mps_thr_t thread, void *p, size_t s)
|
||||
{
|
||||
ScanState ss = PARENT(ScanStateStruct, ss_s, mps_ss);
|
||||
UNUSED(mps_ss);
|
||||
UNUSED(thread);
|
||||
UNUSED(p);
|
||||
UNUSED(s);
|
||||
return ThreadScan(ss, thread, p);
|
||||
|
||||
NOTREACHED;
|
||||
|
||||
return ResUNIMPL;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -596,11 +596,16 @@ int main(int argc, char *argv[])
|
|||
"arena_create");
|
||||
die(mps_thread_reg(&thread, arena), "thread_reg");
|
||||
|
||||
if (rnd() % 2) {
|
||||
die(mps_root_create_reg(®_root, arena,
|
||||
mps_rank_ambig(), (mps_rm_t)0,
|
||||
thread, &mps_stack_scan_ambig,
|
||||
marker, (size_t)0),
|
||||
"root_create_reg");
|
||||
} else {
|
||||
die(mps_root_create_thread(®_root, arena, thread, marker),
|
||||
"root_create_thread");
|
||||
}
|
||||
|
||||
mps_tramp(&r, test, arena, 0);
|
||||
mps_root_destroy(reg_root);
|
||||
|
|
|
|||
|
|
@ -261,6 +261,23 @@
|
|||
#define MPS_PF_ALIGN 4
|
||||
|
||||
|
||||
#elif defined(__FreeBSD__) && defined (__i386__) && defined (__GNUC__) \
|
||||
&& defined(__clang__)
|
||||
#if defined(CONFIG_PF_STRING) && ! defined(CONFIG_PF_FRI3LL)
|
||||
#error "specified CONFIG_PF_... inconsistent with detected fri3ll"
|
||||
#endif
|
||||
#define MPS_PF_FRI3LL
|
||||
#define MPS_PF_STRING "fri3ll"
|
||||
#define MPS_OS_FR
|
||||
#define MPS_ARCH_I3
|
||||
#define MPS_BUILD_LL
|
||||
#define MPS_T_WORD unsigned long
|
||||
#define MPS_T_ULONGEST unsigned long
|
||||
#define MPS_WORD_WIDTH 32
|
||||
#define MPS_WORD_SHIFT 5
|
||||
#define MPS_PF_ALIGN 4
|
||||
|
||||
|
||||
#elif defined(__FreeBSD__) && defined (__x86_64__) && defined (__GNUC__) \
|
||||
&& !defined(__clang__)
|
||||
#if defined(CONFIG_PF_STRING) && ! defined(CONFIG_PF_FRI6GC)
|
||||
|
|
@ -278,6 +295,23 @@
|
|||
#define MPS_PF_ALIGN 8
|
||||
|
||||
|
||||
#elif defined(__FreeBSD__) && defined (__x86_64__) && defined (__GNUC__) \
|
||||
&& defined(__clang__)
|
||||
#if defined(CONFIG_PF_STRING) && ! defined(CONFIG_PF_FRI6LL)
|
||||
#error "specified CONFIG_PF_... inconsistent with detected fri6ll"
|
||||
#endif
|
||||
#define MPS_PF_FRI6LL
|
||||
#define MPS_PF_STRING "fri6ll"
|
||||
#define MPS_OS_FR
|
||||
#define MPS_ARCH_I6
|
||||
#define MPS_BUILD_LL
|
||||
#define MPS_T_WORD unsigned long
|
||||
#define MPS_T_ULONGEST unsigned long /* FIXME: Check this for Clang */
|
||||
#define MPS_WORD_WIDTH 64
|
||||
#define MPS_WORD_SHIFT 6
|
||||
#define MPS_PF_ALIGN 8
|
||||
|
||||
|
||||
#else
|
||||
#error "The MPS Kit does not have a configuration for this platform out of the box; see manual/build.txt"
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* policy.c: POLICY DECISIONS
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2015 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* This module collects the decision-making code for the MPS, so that
|
||||
* policy can be maintained and adjusted.
|
||||
|
|
@ -9,7 +9,7 @@
|
|||
* .sources: <design/strategy/>.
|
||||
*/
|
||||
|
||||
#include "chain.h"
|
||||
#include "locus.h"
|
||||
#include "mpm.h"
|
||||
|
||||
SRCID(policy, "$Id$");
|
||||
|
|
@ -394,7 +394,7 @@ Bool PolicyPollAgain(Arena arena, Clock start, Size tracedSize)
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2015 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
/* poolamc.c: AUTOMATIC MOSTLY-COPYING MEMORY POOL CLASS
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license.
|
||||
* Portions copyright (C) 2002 Global Graphics Software.
|
||||
*
|
||||
* .sources: <design/poolamc/>.
|
||||
*/
|
||||
|
||||
#include "mpscamc.h"
|
||||
#include "chain.h"
|
||||
#include "locus.h"
|
||||
#include "bt.h"
|
||||
#include "mpm.h"
|
||||
#include "nailboard.h"
|
||||
|
|
@ -1252,7 +1252,7 @@ static Res AMCWhiten(Pool pool, Trace trace, Seg seg)
|
|||
* limit have been scanned. It is not touched otherwise.
|
||||
*/
|
||||
static Res amcScanNailedRange(Bool *totalReturn, Bool *moreReturn,
|
||||
Size *bytesScanned, ScanState ss,
|
||||
ScanState ss,
|
||||
AMC amc, Nailboard board,
|
||||
Addr base, Addr limit)
|
||||
{
|
||||
|
|
@ -1268,14 +1268,12 @@ static Res amcScanNailedRange(Bool *totalReturn, Bool *moreReturn,
|
|||
Addr q;
|
||||
q = (*format->skip)(p);
|
||||
if ((*amc->pinned)(amc, board, p, q)) {
|
||||
Res res;
|
||||
res = (*format->scan)(&ss->ss_s, p, q);
|
||||
Res res = FormatScan(format, ss, p, q);
|
||||
if(res != ResOK) {
|
||||
*totalReturn = FALSE;
|
||||
*moreReturn = TRUE;
|
||||
return res;
|
||||
}
|
||||
*bytesScanned += AddrOffset(p, q);
|
||||
} else {
|
||||
*totalReturn = FALSE;
|
||||
}
|
||||
|
|
@ -1300,7 +1298,6 @@ static Res amcScanNailedOnce(Bool *totalReturn, Bool *moreReturn,
|
|||
ScanState ss, Seg seg, AMC amc)
|
||||
{
|
||||
Addr p, limit;
|
||||
Size bytesScanned = 0;
|
||||
Nailboard board;
|
||||
Res res;
|
||||
|
||||
|
|
@ -1317,7 +1314,7 @@ static Res amcScanNailedOnce(Bool *totalReturn, Bool *moreReturn,
|
|||
AVER(p == limit);
|
||||
goto returnGood;
|
||||
}
|
||||
res = amcScanNailedRange(totalReturn, moreReturn, &bytesScanned,
|
||||
res = amcScanNailedRange(totalReturn, moreReturn,
|
||||
ss, amc, board, p, limit);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
|
|
@ -1326,7 +1323,7 @@ static Res amcScanNailedOnce(Bool *totalReturn, Bool *moreReturn,
|
|||
|
||||
limit = SegLimit(seg);
|
||||
/* @@@@ Shouldn't p be set to BufferLimit here?! */
|
||||
res = amcScanNailedRange(totalReturn, moreReturn, &bytesScanned,
|
||||
res = amcScanNailedRange(totalReturn, moreReturn,
|
||||
ss, amc, board, p, limit);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
|
|
@ -1334,8 +1331,6 @@ static Res amcScanNailedOnce(Bool *totalReturn, Bool *moreReturn,
|
|||
returnGood:
|
||||
EVENT3(AMCScanEnd, amc, seg, ss); /* TODO: consider using own event */
|
||||
|
||||
AVER(bytesScanned <= SegSize(seg));
|
||||
ss->scannedSize += bytesScanned;
|
||||
*moreReturn = NailboardNewNails(board);
|
||||
return ResOK;
|
||||
}
|
||||
|
|
@ -1426,12 +1421,11 @@ static Res AMCScan(Bool *totalReturn, ScanState ss, Pool pool, Seg seg)
|
|||
*totalReturn = TRUE;
|
||||
return ResOK;
|
||||
}
|
||||
res = (*format->scan)(&ss->ss_s, base, limit);
|
||||
res = FormatScan(format, ss, base, limit);
|
||||
if(res != ResOK) {
|
||||
*totalReturn = FALSE;
|
||||
return res;
|
||||
}
|
||||
ss->scannedSize += AddrOffset(base, limit);
|
||||
base = limit;
|
||||
}
|
||||
|
||||
|
|
@ -1440,14 +1434,13 @@ static Res AMCScan(Bool *totalReturn, ScanState ss, Pool pool, Seg seg)
|
|||
AVER(SegBase(seg) <= base);
|
||||
AVER(base <= AddrAdd(SegLimit(seg), format->headerSize));
|
||||
if(base < limit) {
|
||||
res = (*format->scan)(&ss->ss_s, base, limit);
|
||||
res = FormatScan(format, ss, base, limit);
|
||||
if(res != ResOK) {
|
||||
*totalReturn = FALSE;
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
ss->scannedSize += AddrOffset(base, limit);
|
||||
EVENT3(AMCScanEnd, amc, seg, ss);
|
||||
|
||||
*totalReturn = TRUE;
|
||||
|
|
@ -2261,7 +2254,7 @@ static Bool AMCCheck(AMC amc)
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* poolams.c: AUTOMATIC MARK & SWEEP POOL CLASS
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license.
|
||||
* Portions copyright (c) 2002 Global Graphics Software.
|
||||
*
|
||||
*
|
||||
|
|
@ -1318,12 +1318,12 @@ static Res amsScanObject(Seg seg, Index i, Addr p, Addr next, void *clos)
|
|||
|
||||
/* @@@@ This isn't quite right for multiple traces. */
|
||||
if (closure->scanAllObjects || AMS_IS_GREY(seg, i)) {
|
||||
res = (*format->scan)(&closure->ss->ss_s,
|
||||
res = FormatScan(format,
|
||||
closure->ss,
|
||||
AddrAdd(p, format->headerSize),
|
||||
AddrAdd(next, format->headerSize));
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
closure->ss->scannedSize += AddrOffset(p, next);
|
||||
if (!closure->scanAllObjects) {
|
||||
Index j = AMS_ADDR_INDEX(seg, next);
|
||||
AVER(!AMS_IS_INVALID_COLOUR(seg, i));
|
||||
|
|
@ -1412,7 +1412,7 @@ Res AMSScan(Bool *totalReturn, ScanState ss, Pool pool, Seg seg)
|
|||
next = AddrAdd(p, alignment);
|
||||
}
|
||||
j = AMS_ADDR_INDEX(seg, next);
|
||||
res = (*format->scan)(&ss->ss_s, clientP, clientNext);
|
||||
res = FormatScan(format, ss, clientP, clientNext);
|
||||
if (res != ResOK) {
|
||||
/* <design/poolams/#marked.scan.fail> */
|
||||
amsseg->marksChanged = TRUE;
|
||||
|
|
@ -1422,7 +1422,6 @@ Res AMSScan(Bool *totalReturn, ScanState ss, Pool pool, Seg seg)
|
|||
/* Check that there haven't been any ambiguous fixes during the */
|
||||
/* scan, because AMSFindGrey won't work otherwise. */
|
||||
AVER_CRITICAL(!amsseg->ambiguousFixes);
|
||||
ss->scannedSize += AddrOffset(p, next);
|
||||
AMS_GREY_BLACKEN(seg, i);
|
||||
if (i+1 < j)
|
||||
AMS_RANGE_WHITE_BLACKEN(seg, i+1, j);
|
||||
|
|
@ -1809,6 +1808,22 @@ DEFINE_POOL_CLASS(AMSDebugPoolClass, this)
|
|||
}
|
||||
|
||||
|
||||
/* mps_class_ams -- return the AMS pool class descriptor */
|
||||
|
||||
mps_pool_class_t mps_class_ams(void)
|
||||
{
|
||||
return (mps_pool_class_t)AMSPoolClassGet();
|
||||
}
|
||||
|
||||
|
||||
/* mps_class_ams_debug -- return the AMS (debug) pool class descriptor */
|
||||
|
||||
mps_pool_class_t mps_class_ams_debug(void)
|
||||
{
|
||||
return (mps_pool_class_t)AMSDebugPoolClassGet();
|
||||
}
|
||||
|
||||
|
||||
/* AMSCheck -- the check method for an AMS */
|
||||
|
||||
Bool AMSCheck(AMS ams)
|
||||
|
|
@ -1831,7 +1846,7 @@ Bool AMSCheck(AMS ams)
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,69 +0,0 @@
|
|||
/* poolamsi.c: AUTOMATIC MARK & SWEEP POOL CLASS C INTERFACE
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
*/
|
||||
|
||||
#include "mpscams.h"
|
||||
#include "mps.h"
|
||||
#include "poolams.h"
|
||||
|
||||
SRCID(poolamsi, "$Id$");
|
||||
|
||||
|
||||
/* mps_class_ams -- return the AMS pool class descriptor */
|
||||
|
||||
mps_pool_class_t mps_class_ams(void)
|
||||
{
|
||||
return (mps_pool_class_t)AMSPoolClassGet();
|
||||
}
|
||||
|
||||
|
||||
/* mps_class_ams_debug -- return the AMS (debug) pool class descriptor */
|
||||
|
||||
mps_pool_class_t mps_class_ams_debug(void)
|
||||
{
|
||||
return (mps_pool_class_t)AMSDebugPoolClassGet();
|
||||
}
|
||||
|
||||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Redistributions in any form must be accompanied by information on how
|
||||
* to obtain complete source code for this software and any accompanying
|
||||
* software that uses this software. The source code must either be
|
||||
* included in the distribution or be available for no more than the cost
|
||||
* of distribution plus a nominal fee, and must be freely redistributable
|
||||
* under reasonable conditions. For an executable file, complete source
|
||||
* code means the source code for all modules it contains. It does not
|
||||
* include source code for modules or files that typically accompany the
|
||||
* major components of the operating system on which the executable file
|
||||
* runs.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
/* poolawl.c: AUTOMATIC WEAK LINKED POOL CLASS
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2015 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
*
|
||||
* DESIGN
|
||||
|
|
@ -41,7 +41,7 @@
|
|||
|
||||
#include "mpscawl.h"
|
||||
#include "mpm.h"
|
||||
#include "chain.h"
|
||||
#include "locus.h"
|
||||
|
||||
SRCID(poolawl, "$Id$");
|
||||
|
||||
|
|
@ -901,9 +901,7 @@ static Res awlScanObject(Arena arena, AWL awl, ScanState ss,
|
|||
SegSetSummary(dependentSeg, RefSetUNIV);
|
||||
}
|
||||
|
||||
res = (*format->scan)(&ss->ss_s, base, limit);
|
||||
if (res == ResOK)
|
||||
ss->scannedSize += AddrOffset(base, limit);
|
||||
res = FormatScan(format, ss, base, limit);
|
||||
|
||||
if (dependent)
|
||||
ShieldCover(arena, dependentSeg);
|
||||
|
|
@ -1376,7 +1374,7 @@ static Bool AWLCheck(AWL awl)
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2015 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -527,7 +527,7 @@ static Res SNCScan(Bool *totalReturn, ScanState ss, Pool pool, Seg seg)
|
|||
}
|
||||
|
||||
if (base < limit) {
|
||||
res = (*format->scan)(&ss->ss_s, base, limit);
|
||||
res = FormatScan(format, ss, base, limit);
|
||||
if (res != ResOK) {
|
||||
*totalReturn = FALSE;
|
||||
return res;
|
||||
|
|
@ -536,8 +536,6 @@ static Res SNCScan(Bool *totalReturn, ScanState ss, Pool pool, Seg seg)
|
|||
AVER(base == limit);
|
||||
}
|
||||
|
||||
ss->scannedSize += AddrOffset(base, limit);
|
||||
|
||||
*totalReturn = TRUE;
|
||||
return ResOK;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,17 +38,20 @@ Addr MutatorFaultContextSP(MutatorFaultContext mfc)
|
|||
}
|
||||
|
||||
|
||||
Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc)
|
||||
Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc,
|
||||
mps_area_scan_t scan_area,
|
||||
void *closure)
|
||||
{
|
||||
Res res;
|
||||
|
||||
/* This scans the root registers (.context.regroots). It also unnecessarily
|
||||
scans the rest of the context. The optimisation to scan only relevant
|
||||
parts would be machine dependent. */
|
||||
res = TraceScanAreaTagged(
|
||||
res = TraceScanArea(
|
||||
ss,
|
||||
(Addr *)mfc->ucontext,
|
||||
(Addr *)((char *)mfc->ucontext + sizeof(*(mfc->ucontext)))
|
||||
(Word *)mfc->ucontext,
|
||||
(Word *)((char *)mfc->ucontext + sizeof(*(mfc->ucontext))),
|
||||
scan_area, closure
|
||||
);
|
||||
|
||||
return res;
|
||||
|
|
|
|||
|
|
@ -101,7 +101,9 @@ Addr MutatorFaultContextSP(MutatorFaultContext mfc)
|
|||
}
|
||||
|
||||
|
||||
Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc)
|
||||
Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc,
|
||||
mps_area_scan_t scan_area,
|
||||
void *closure)
|
||||
{
|
||||
mcontext_t *mc;
|
||||
Res res;
|
||||
|
|
@ -110,9 +112,10 @@ Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc)
|
|||
unnecessarily scans the rest of the context. The optimisation
|
||||
to scan only relevant parts would be machine dependent. */
|
||||
mc = &mfc->ucontext->uc_mcontext;
|
||||
res = TraceScanAreaTagged(ss,
|
||||
(Addr *)mc,
|
||||
(Addr *)((char *)mc + sizeof(*mc)));
|
||||
res = TraceScanArea(ss,
|
||||
(Word *)mc,
|
||||
(Word *)((char *)mc + sizeof(*mc)),
|
||||
scan_area, closure);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -96,7 +96,9 @@ Addr MutatorFaultContextSP(MutatorFaultContext mfc)
|
|||
}
|
||||
|
||||
|
||||
Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc)
|
||||
Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc,
|
||||
mps_area_scan_t scan_area,
|
||||
void *closure)
|
||||
{
|
||||
x86_thread_state32_t *mc;
|
||||
Res res;
|
||||
|
|
@ -105,9 +107,10 @@ Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc)
|
|||
unnecessarily scans the rest of the context. The optimisation
|
||||
to scan only relevant parts would be machine dependent. */
|
||||
mc = mfc->threadState;
|
||||
res = TraceScanAreaTagged(ss,
|
||||
(Addr *)mc,
|
||||
(Addr *)((char *)mc + sizeof(*mc)));
|
||||
res = TraceScanArea(ss,
|
||||
(Word *)mc,
|
||||
(Word *)((char *)mc + sizeof(*mc)),
|
||||
scan_area, closure);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -32,17 +32,20 @@ Addr MutatorFaultContextSP(MutatorFaultContext mfc)
|
|||
}
|
||||
|
||||
|
||||
Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc)
|
||||
Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc,
|
||||
mps_area_scan_t scan_area,
|
||||
void *closure)
|
||||
{
|
||||
Res res;
|
||||
|
||||
/* This scans the root registers (.context.regroots). It also unnecessarily
|
||||
scans the rest of the context. The optimisation to scan only relevant
|
||||
parts would be machine dependent. */
|
||||
res = TraceScanAreaTagged(
|
||||
res = TraceScanArea(
|
||||
ss,
|
||||
(Addr *)mfc->ucontext,
|
||||
(Addr *)((char *)mfc->ucontext + sizeof(*(mfc->ucontext)))
|
||||
(Word *)mfc->ucontext,
|
||||
(Word *)((char *)mfc->ucontext + sizeof(*(mfc->ucontext))),
|
||||
scan_area, closure
|
||||
);
|
||||
|
||||
return res;
|
||||
|
|
|
|||
|
|
@ -105,7 +105,9 @@ Addr MutatorFaultContextSP(MutatorFaultContext mfc)
|
|||
}
|
||||
|
||||
|
||||
Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc)
|
||||
Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc,
|
||||
mps_area_scan_t scan_area,
|
||||
void *closure)
|
||||
{
|
||||
mcontext_t *mc;
|
||||
Res res;
|
||||
|
|
@ -114,9 +116,10 @@ Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc)
|
|||
unnecessarily scans the rest of the context. The optimisation
|
||||
to scan only relevant parts would be machine dependent. */
|
||||
mc = &mfc->ucontext->uc_mcontext;
|
||||
res = TraceScanAreaTagged(ss,
|
||||
(Addr *)mc,
|
||||
(Addr *)((char *)mc + sizeof(*mc)));
|
||||
res = TraceScanArea(ss,
|
||||
(Word *)mc,
|
||||
(Word *)((char *)mc + sizeof(*mc)),
|
||||
scan_area, closure);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -99,7 +99,9 @@ Addr MutatorFaultContextSP(MutatorFaultContext mfc)
|
|||
}
|
||||
|
||||
|
||||
Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc)
|
||||
Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc,
|
||||
mps_area_scan_t scan_area,
|
||||
void *closure)
|
||||
{
|
||||
x86_thread_state64_t *mc;
|
||||
Res res;
|
||||
|
|
@ -108,9 +110,10 @@ Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc)
|
|||
unnecessarily scans the rest of the context. The optimisation
|
||||
to scan only relevant parts would be machine dependent. */
|
||||
mc = mfc->threadState;
|
||||
res = TraceScanAreaTagged(ss,
|
||||
(Addr *)mc,
|
||||
(Addr *)((char *)mc + sizeof(*mc)));
|
||||
res = TraceScanArea(ss,
|
||||
(Word *)mc,
|
||||
(Word *)((char *)mc + sizeof(*mc)),
|
||||
scan_area, closure);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -30,7 +30,9 @@ extern void ProtSync(Arena arena);
|
|||
extern Bool ProtCanStepInstruction(MutatorFaultContext context);
|
||||
extern Res ProtStepInstruction(MutatorFaultContext context);
|
||||
extern Addr MutatorFaultContextSP(MutatorFaultContext mfc);
|
||||
extern Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc);
|
||||
extern Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc,
|
||||
mps_area_scan_t scan,
|
||||
void *closure);
|
||||
|
||||
|
||||
#endif /* prot_h */
|
||||
|
|
|
|||
242
mps/code/root.c
242
mps/code/root.c
|
|
@ -1,7 +1,7 @@
|
|||
/* root.c: ROOT IMPLEMENTATION
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2015 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* .purpose: This is the implementation of the root datatype.
|
||||
*
|
||||
|
|
@ -17,6 +17,11 @@ SRCID(root, "$Id$");
|
|||
|
||||
#define RootSig ((Sig)0x51960029) /* SIGnature ROOT */
|
||||
|
||||
typedef union AreaScanUnion {
|
||||
void *closure;
|
||||
mps_scan_tag_s tag; /* tag for scanning */
|
||||
} AreaScanUnion;
|
||||
|
||||
typedef struct RootStruct {
|
||||
Sig sig;
|
||||
Serial serial; /* from arena->rootSerial */
|
||||
|
|
@ -34,24 +39,21 @@ typedef struct RootStruct {
|
|||
union RootUnion {
|
||||
struct {
|
||||
mps_root_scan_t scan; /* the function which does the scanning */
|
||||
void *p; /* environment for scan */
|
||||
size_t s; /* environment for scan */
|
||||
void *p; /* closure for scan function */
|
||||
size_t s; /* closure for scan function */
|
||||
} fun;
|
||||
struct {
|
||||
Addr *base; /* beginning of table */
|
||||
Addr *limit; /* one off end of table */
|
||||
} table;
|
||||
Word *base; /* base of area to be scanned */
|
||||
Word *limit; /* limit of area to be scanned */
|
||||
mps_area_scan_t scan_area;/* area scanning function */
|
||||
AreaScanUnion the;
|
||||
} area;
|
||||
struct {
|
||||
Addr *base; /* beginning of table */
|
||||
Addr *limit; /* one off end of table */
|
||||
Word mask; /* tag mask for scanning */
|
||||
} tableMasked;
|
||||
struct {
|
||||
mps_reg_scan_t scan; /* function for scanning registers */
|
||||
Thread thread; /* passed to scan */
|
||||
void *p; /* passed to scan */
|
||||
size_t s; /* passed to scan */
|
||||
} reg;
|
||||
mps_area_scan_t scan_area;/* area scanner for stack and registers */
|
||||
AreaScanUnion the;
|
||||
Word *stackCold; /* cold end of stack */
|
||||
} thread;
|
||||
struct {
|
||||
mps_fmt_scan_t scan; /* format-like scanner */
|
||||
Addr base, limit; /* passed to scan */
|
||||
|
|
@ -66,8 +68,10 @@ typedef struct RootStruct {
|
|||
|
||||
Bool RootVarCheck(RootVar rootVar)
|
||||
{
|
||||
CHECKL(rootVar == RootTABLE || rootVar == RootTABLE_MASKED
|
||||
|| rootVar == RootFUN || rootVar == RootFMT || rootVar == RootREG);
|
||||
CHECKL(rootVar == RootAREA || rootVar == RootAREA_TAGGED
|
||||
|| rootVar == RootFUN || rootVar == RootFMT
|
||||
|| rootVar == RootTHREAD
|
||||
|| rootVar == RootTHREAD_TAGGED);
|
||||
UNUSED(rootVar);
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -104,24 +108,33 @@ Bool RootCheck(Root root)
|
|||
/* Don't need to check var here, because of the switch below */
|
||||
switch(root->var)
|
||||
{
|
||||
case RootTABLE:
|
||||
CHECKL(root->the.table.base != 0);
|
||||
CHECKL(root->the.table.base < root->the.table.limit);
|
||||
case RootAREA:
|
||||
CHECKL(root->the.area.base != 0);
|
||||
CHECKL(root->the.area.base < root->the.area.limit);
|
||||
CHECKL(FUNCHECK(root->the.area.scan_area));
|
||||
/* Can't check anything about closure */
|
||||
break;
|
||||
|
||||
case RootTABLE_MASKED:
|
||||
CHECKL(root->the.tableMasked.base != 0);
|
||||
CHECKL(root->the.tableMasked.base < root->the.tableMasked.limit);
|
||||
/* Can't check anything about the mask. */
|
||||
case RootAREA_TAGGED:
|
||||
CHECKL(root->the.area.base != 0);
|
||||
CHECKL(root->the.area.base < root->the.area.limit);
|
||||
CHECKL(FUNCHECK(root->the.area.scan_area));
|
||||
/* Can't check anything about tag as it could mean anything to
|
||||
scan_area. */
|
||||
break;
|
||||
|
||||
case RootFUN:
|
||||
CHECKL(root->the.fun.scan != NULL);
|
||||
/* Can't check anything about closure as it could mean anything to
|
||||
scan. */
|
||||
break;
|
||||
|
||||
case RootREG:
|
||||
CHECKL(root->the.reg.scan != NULL);
|
||||
CHECKD_NOSIG(Thread, root->the.reg.thread); /* <design/check/#hidden-type> */
|
||||
case RootTHREAD_TAGGED:
|
||||
CHECKD_NOSIG(Thread, root->the.thread.thread); /* <design/check/#hidden-type> */
|
||||
CHECKL(FUNCHECK(root->the.thread.scan_area));
|
||||
/* Can't check anything about tag as it could mean anything to
|
||||
scan_area. */
|
||||
/* Can't check anything about stackCold. */
|
||||
break;
|
||||
|
||||
case RootFMT:
|
||||
|
|
@ -149,7 +162,7 @@ Bool RootCheck(Root root)
|
|||
}
|
||||
|
||||
|
||||
/* rootCreate, RootCreateTable, RootCreateReg, RootCreateFmt, RootCreateFun
|
||||
/* rootCreate, RootCreateArea, RootCreateThread, RootCreateFmt, RootCreateFun
|
||||
*
|
||||
* RootCreate* set up the appropriate union member, and call the generic
|
||||
* create function to do the actual creation
|
||||
|
|
@ -168,6 +181,7 @@ static Res rootCreate(Root *rootReturn, Arena arena,
|
|||
AVER(rootReturn != NULL);
|
||||
AVERT(Arena, arena);
|
||||
AVERT(Rank, rank);
|
||||
AVERT(RootMode, mode);
|
||||
AVERT(RootVar, type);
|
||||
globals = ArenaGlobals(arena);
|
||||
|
||||
|
|
@ -253,8 +267,11 @@ static Res rootCreateProtectable(Root *rootReturn, Arena arena,
|
|||
return ResOK;
|
||||
}
|
||||
|
||||
Res RootCreateTable(Root *rootReturn, Arena arena,
|
||||
Rank rank, RootMode mode, Addr *base, Addr *limit)
|
||||
Res RootCreateArea(Root *rootReturn, Arena arena,
|
||||
Rank rank, RootMode mode,
|
||||
Word *base, Word *limit,
|
||||
mps_area_scan_t scan_area,
|
||||
void *closure)
|
||||
{
|
||||
Res res;
|
||||
union RootUnion theUnion;
|
||||
|
|
@ -262,43 +279,54 @@ Res RootCreateTable(Root *rootReturn, Arena arena,
|
|||
AVER(rootReturn != NULL);
|
||||
AVERT(Arena, arena);
|
||||
AVERT(Rank, rank);
|
||||
AVERT(RootMode, mode);
|
||||
AVER(base != 0);
|
||||
AVER(AddrIsAligned(base, sizeof(Word)));
|
||||
AVER(base < limit);
|
||||
AVER(AddrIsAligned(limit, sizeof(Word)));
|
||||
AVER(FUNCHECK(scan_area));
|
||||
/* Can't check anything about closure */
|
||||
|
||||
theUnion.table.base = base;
|
||||
theUnion.table.limit = limit;
|
||||
theUnion.area.base = base;
|
||||
theUnion.area.limit = limit;
|
||||
theUnion.area.scan_area = scan_area;
|
||||
theUnion.area.the.closure = closure;
|
||||
|
||||
res = rootCreateProtectable(rootReturn, arena, rank, mode,
|
||||
RootTABLE, (Addr)base, (Addr)limit, &theUnion);
|
||||
RootAREA, (Addr)base, (Addr)limit, &theUnion);
|
||||
return res;
|
||||
}
|
||||
|
||||
Res RootCreateTableMasked(Root *rootReturn, Arena arena,
|
||||
Rank rank, RootMode mode, Addr *base, Addr *limit,
|
||||
Word mask)
|
||||
Res RootCreateAreaTagged(Root *rootReturn, Arena arena,
|
||||
Rank rank, RootMode mode, Word *base, Word *limit,
|
||||
mps_area_scan_t scan_area, Word mask, Word pattern)
|
||||
{
|
||||
union RootUnion theUnion;
|
||||
|
||||
AVER(rootReturn != NULL);
|
||||
AVERT(Arena, arena);
|
||||
AVERT(Rank, rank);
|
||||
AVERT(RootMode, mode);
|
||||
AVER(base != 0);
|
||||
AVER(base < limit);
|
||||
/* Can't check anything about mask. */
|
||||
/* Can't check anything about mask or pattern, as they could mean
|
||||
anything to scan_area. */
|
||||
|
||||
theUnion.tableMasked.base = base;
|
||||
theUnion.tableMasked.limit = limit;
|
||||
theUnion.tableMasked.mask = mask;
|
||||
theUnion.area.base = base;
|
||||
theUnion.area.limit = limit;
|
||||
theUnion.area.scan_area = scan_area;
|
||||
theUnion.area.the.tag.mask = mask;
|
||||
theUnion.area.the.tag.pattern = pattern;
|
||||
|
||||
return rootCreateProtectable(rootReturn, arena, rank, mode, RootTABLE_MASKED,
|
||||
return rootCreateProtectable(rootReturn, arena, rank, mode, RootAREA_TAGGED,
|
||||
(Addr)base, (Addr)limit, &theUnion);
|
||||
}
|
||||
|
||||
Res RootCreateReg(Root *rootReturn, Arena arena,
|
||||
Res RootCreateThread(Root *rootReturn, Arena arena,
|
||||
Rank rank, Thread thread,
|
||||
mps_reg_scan_t scan, void *p, size_t s)
|
||||
mps_area_scan_t scan_area,
|
||||
void *closure,
|
||||
Word *stackCold)
|
||||
{
|
||||
union RootUnion theUnion;
|
||||
|
||||
|
|
@ -307,14 +335,43 @@ Res RootCreateReg(Root *rootReturn, Arena arena,
|
|||
AVERT(Rank, rank);
|
||||
AVERT(Thread, thread);
|
||||
AVER(ThreadArena(thread) == arena);
|
||||
AVER(scan != NULL);
|
||||
AVER(FUNCHECK(scan_area));
|
||||
/* Can't check anything about closure. */
|
||||
|
||||
theUnion.reg.scan = scan;
|
||||
theUnion.reg.thread = thread;
|
||||
theUnion.reg.p = p;
|
||||
theUnion.reg.s = s;
|
||||
theUnion.thread.thread = thread;
|
||||
theUnion.thread.scan_area = scan_area;
|
||||
theUnion.thread.the.closure = closure;
|
||||
theUnion.thread.stackCold = stackCold;
|
||||
|
||||
return rootCreate(rootReturn, arena, rank, (RootMode)0, RootREG, &theUnion);
|
||||
return rootCreate(rootReturn, arena, rank, (RootMode)0, RootTHREAD,
|
||||
&theUnion);
|
||||
}
|
||||
|
||||
Res RootCreateThreadTagged(Root *rootReturn, Arena arena,
|
||||
Rank rank, Thread thread,
|
||||
mps_area_scan_t scan_area,
|
||||
Word mask, Word pattern,
|
||||
Word *stackCold)
|
||||
{
|
||||
union RootUnion theUnion;
|
||||
|
||||
AVER(rootReturn != NULL);
|
||||
AVERT(Arena, arena);
|
||||
AVERT(Rank, rank);
|
||||
AVERT(Thread, thread);
|
||||
AVER(ThreadArena(thread) == arena);
|
||||
AVER(FUNCHECK(scan_area));
|
||||
/* Can't check anything about mask or pattern, as they could mean
|
||||
anything to scan_area. */
|
||||
|
||||
theUnion.thread.thread = thread;
|
||||
theUnion.thread.scan_area = scan_area;
|
||||
theUnion.thread.the.tag.mask = mask;
|
||||
theUnion.thread.the.tag.pattern = pattern;
|
||||
theUnion.thread.stackCold = stackCold;
|
||||
|
||||
return rootCreate(rootReturn, arena, rank, (RootMode)0, RootTHREAD_TAGGED,
|
||||
&theUnion);
|
||||
}
|
||||
|
||||
/* RootCreateFmt -- create root from block of formatted objects
|
||||
|
|
@ -333,6 +390,7 @@ Res RootCreateFmt(Root *rootReturn, Arena arena,
|
|||
AVER(rootReturn != NULL);
|
||||
AVERT(Arena, arena);
|
||||
AVERT(Rank, rank);
|
||||
AVERT(RootMode, mode);
|
||||
AVER(FUNCHECK(scan));
|
||||
AVER(base != 0);
|
||||
AVER(base < limit);
|
||||
|
|
@ -470,32 +528,48 @@ Res RootScan(ScanState ss, Root root)
|
|||
}
|
||||
|
||||
switch(root->var) {
|
||||
case RootTABLE:
|
||||
res = TraceScanArea(ss, root->the.table.base, root->the.table.limit);
|
||||
ss->scannedSize += AddrOffset(root->the.table.base, root->the.table.limit);
|
||||
case RootAREA:
|
||||
res = TraceScanArea(ss,
|
||||
root->the.area.base,
|
||||
root->the.area.limit,
|
||||
root->the.area.scan_area,
|
||||
root->the.area.the.closure);
|
||||
if (res != ResOK)
|
||||
goto failScan;
|
||||
break;
|
||||
|
||||
case RootTABLE_MASKED:
|
||||
res = TraceScanAreaMasked(ss,
|
||||
root->the.tableMasked.base,
|
||||
root->the.tableMasked.limit,
|
||||
root->the.tableMasked.mask);
|
||||
ss->scannedSize += AddrOffset(root->the.table.base, root->the.table.limit);
|
||||
case RootAREA_TAGGED:
|
||||
res = TraceScanArea(ss,
|
||||
root->the.area.base,
|
||||
root->the.area.limit,
|
||||
root->the.area.scan_area,
|
||||
&root->the.area.the.tag);
|
||||
if (res != ResOK)
|
||||
goto failScan;
|
||||
break;
|
||||
|
||||
case RootFUN:
|
||||
res = (*root->the.fun.scan)(&ss->ss_s, root->the.fun.p, root->the.fun.s);
|
||||
res = root->the.fun.scan(&ss->ss_s,
|
||||
root->the.fun.p,
|
||||
root->the.fun.s);
|
||||
if (res != ResOK)
|
||||
goto failScan;
|
||||
break;
|
||||
|
||||
case RootREG:
|
||||
res = (*root->the.reg.scan)(&ss->ss_s, root->the.reg.thread,
|
||||
root->the.reg.p, root->the.reg.s);
|
||||
case RootTHREAD:
|
||||
res = ThreadScan(ss, root->the.thread.thread,
|
||||
root->the.thread.stackCold,
|
||||
root->the.thread.scan_area,
|
||||
root->the.thread.the.closure);
|
||||
if (res != ResOK)
|
||||
goto failScan;
|
||||
break;
|
||||
|
||||
case RootTHREAD_TAGGED:
|
||||
res = ThreadScan(ss, root->the.thread.thread,
|
||||
root->the.thread.stackCold,
|
||||
root->the.thread.scan_area,
|
||||
&root->the.thread.the.tag);
|
||||
if (res != ResOK)
|
||||
goto failScan;
|
||||
break;
|
||||
|
|
@ -624,22 +698,24 @@ Res RootDescribe(Root root, mps_lib_FILE *stream, Count depth)
|
|||
return res;
|
||||
|
||||
switch(root->var) {
|
||||
case RootTABLE:
|
||||
case RootAREA:
|
||||
res = WriteF(stream, depth + 2,
|
||||
"table base $A limit $A\n",
|
||||
(WriteFA)root->the.table.base,
|
||||
(WriteFA)root->the.table.limit,
|
||||
"area base $A limit $A scan_area closure $P\n",
|
||||
(WriteFA)root->the.area.base,
|
||||
(WriteFA)root->the.area.limit,
|
||||
(WriteFP)root->the.area.the.closure,
|
||||
NULL);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
break;
|
||||
|
||||
case RootTABLE_MASKED:
|
||||
case RootAREA_TAGGED:
|
||||
res = WriteF(stream, depth + 2,
|
||||
"table base $A limit $A mask $B\n",
|
||||
(WriteFA)root->the.tableMasked.base,
|
||||
(WriteFA)root->the.tableMasked.limit,
|
||||
(WriteFB)root->the.tableMasked.mask,
|
||||
"area base $A limit $A scan_area mask $B pattern $B\n",
|
||||
(WriteFA)root->the.area.base,
|
||||
(WriteFA)root->the.area.limit,
|
||||
(WriteFB)root->the.area.the.tag.mask,
|
||||
(WriteFB)root->the.area.the.tag.pattern,
|
||||
NULL);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
|
|
@ -649,16 +725,30 @@ Res RootDescribe(Root root, mps_lib_FILE *stream, Count depth)
|
|||
res = WriteF(stream, depth + 2,
|
||||
"scan function $F\n", (WriteFF)root->the.fun.scan,
|
||||
"environment p $P s $W\n",
|
||||
(WriteFP)root->the.fun.p, (WriteFW)root->the.fun.s,
|
||||
(WriteFP)root->the.fun.p,
|
||||
(WriteFW)root->the.fun.s,
|
||||
NULL);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
break;
|
||||
|
||||
case RootREG:
|
||||
case RootTHREAD:
|
||||
res = WriteF(stream, depth + 2,
|
||||
"thread $P\n", (WriteFP)root->the.reg.thread,
|
||||
"environment p $P", (WriteFP)root->the.reg.p,
|
||||
"thread $P\n", (WriteFP)root->the.thread.thread,
|
||||
"closure $P\n",
|
||||
(WriteFP)root->the.thread.the.closure,
|
||||
"stackCold $P\n", (WriteFP)root->the.thread.stackCold,
|
||||
NULL);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
break;
|
||||
|
||||
case RootTHREAD_TAGGED:
|
||||
res = WriteF(stream, depth + 2,
|
||||
"thread $P\n", (WriteFP)root->the.thread.thread,
|
||||
"mask $B\n", (WriteFB)root->the.thread.the.tag.mask,
|
||||
"pattern $B\n", (WriteFB)root->the.thread.the.tag.pattern,
|
||||
"stackCold $P\n", (WriteFP)root->the.thread.stackCold,
|
||||
NULL);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
|
|
@ -707,7 +797,7 @@ Res RootsDescribe(Globals arenaGlobals, mps_lib_FILE *stream, Count depth)
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2015 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@
|
|||
* setjmp magic.
|
||||
*/
|
||||
|
||||
/* StackContextStackTop - return the stack top from the stack context.
|
||||
/* StackContextStackHot - return the hot end of the stack from the stack context
|
||||
*
|
||||
* We assume the stack is full. In other words the stack top points at
|
||||
* a word that contains a potential Ref.
|
||||
|
|
@ -68,7 +68,7 @@ typedef struct StackContextStruct {
|
|||
* which we assume to be stored on the stack because it is no longer
|
||||
* needed once we have _longjmp()ed back. So take the minimum of the
|
||||
* SP and the base of the StackContext structure. */
|
||||
#define StackContextStackTop(sc) \
|
||||
#define StackContextStackHot(sc) \
|
||||
(StackContextSP(sc) < (Addr*)(sc) ? StackContextSP(sc) : (Addr*)(sc))
|
||||
|
||||
|
||||
|
|
@ -103,7 +103,7 @@ typedef struct StackContextStruct {
|
|||
* which we assume to be stored on the stack because it is no longer
|
||||
* needed once we have _longjmp()ed back. So take the minimum of the
|
||||
* SP and the base of the StackContext structure. */
|
||||
#define StackContextStackTop(sc) \
|
||||
#define StackContextStackHot(sc) \
|
||||
(StackContextSP(sc) < (Addr*)(sc) ? StackContextSP(sc) : (Addr*)(sc))
|
||||
|
||||
|
||||
|
|
@ -119,7 +119,7 @@ typedef struct StackContextStruct {
|
|||
|
||||
#define STACK_CONTEXT_SAVE(sc) ((void)setjmp((sc)->jumpBuffer))
|
||||
|
||||
#define StackContextStackTop(sc) \
|
||||
#define StackContextStackHot(sc) \
|
||||
((Addr *)((_JUMP_BUFFER *)(sc)->jumpBuffer)->Esp)
|
||||
|
||||
|
||||
|
|
@ -135,7 +135,7 @@ typedef struct StackContextStruct {
|
|||
|
||||
#define STACK_CONTEXT_SAVE(sc) ((void)setjmp((sc)->jumpBuffer))
|
||||
|
||||
#define StackContextStackTop(sc) \
|
||||
#define StackContextStackHot(sc) \
|
||||
((Addr *)((_JUMP_BUFFER *)(sc)->jumpBuffer)->Rsp)
|
||||
|
||||
|
||||
|
|
@ -155,7 +155,7 @@ typedef struct StackContextStruct {
|
|||
|
||||
#define STACK_CONTEXT_SAVE(sc) ((void)setjmp((sc)->jumpBuffer))
|
||||
|
||||
#define StackContextStackTop(sc) ((Addr *)(sc)->jumpBuffer)
|
||||
#define StackContextStackHot(sc) ((Addr *)(sc)->jumpBuffer)
|
||||
|
||||
|
||||
#endif /* platform defines */
|
||||
|
|
|
|||
187
mps/code/scan.c
Normal file
187
mps/code/scan.c
Normal file
|
|
@ -0,0 +1,187 @@
|
|||
/* scan.c: SCANNING FUNCTIONS
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2016 Ravenbrook Limited.
|
||||
* See end of file for license.
|
||||
*
|
||||
* .outside: The code in this file is written as if *outside* the MPS,
|
||||
* and so is restricted to facilities in the MPS interface. MPS users
|
||||
* are invited to read this code and use it as a basis for their own
|
||||
* scanners. See topic "Area Scanners" in the MPS manual.
|
||||
*
|
||||
* TODO: Design document.
|
||||
*/
|
||||
|
||||
#include "mps.h"
|
||||
#include "mpstd.h" /* for MPS_BUILD_MV */
|
||||
|
||||
|
||||
#ifdef MPS_BUILD_MV
|
||||
/* MSVC warning 4127 = conditional expression is constant */
|
||||
/* Objects to: MPS_SCAN_AREA(1). */
|
||||
#pragma warning( disable : 4127 )
|
||||
#endif
|
||||
|
||||
|
||||
#define MPS_SCAN_AREA(test) \
|
||||
MPS_SCAN_BEGIN(ss) { \
|
||||
mps_word_t *p = base; \
|
||||
while (p < (mps_word_t *)limit) { \
|
||||
mps_word_t word = *p; \
|
||||
mps_word_t tag_bits = word & mask; \
|
||||
if (test) { \
|
||||
mps_addr_t ref = (mps_addr_t)(word ^ tag_bits); \
|
||||
if (MPS_FIX1(ss, ref)) { \
|
||||
mps_res_t res = MPS_FIX2(ss, &ref); \
|
||||
if (res != MPS_RES_OK) \
|
||||
return res; \
|
||||
*p = (mps_word_t)ref | tag_bits; \
|
||||
} \
|
||||
} \
|
||||
++p; \
|
||||
} \
|
||||
} MPS_SCAN_END(ss);
|
||||
|
||||
|
||||
/* mps_scan_area -- scan contiguous area of references
|
||||
*
|
||||
* This is a convenience function for scanning the contiguous area
|
||||
* [base, limit). I.e., it calls Fix on all words from base up to
|
||||
* limit, inclusive of base and exclusive of limit.
|
||||
*
|
||||
* This scanner is appropriate for use when all words in the area are
|
||||
* simple untagged references.
|
||||
*/
|
||||
|
||||
mps_res_t mps_scan_area(mps_ss_t ss,
|
||||
void *base, void *limit,
|
||||
void *closure)
|
||||
{
|
||||
mps_word_t mask = 0;
|
||||
|
||||
(void)closure; /* unused */
|
||||
|
||||
MPS_SCAN_AREA(1);
|
||||
|
||||
return MPS_RES_OK;
|
||||
}
|
||||
|
||||
|
||||
/* mps_scan_area_masked -- scan area masking off tag bits
|
||||
*
|
||||
* Like mps_scan_area, but removes tag bits before fixing references,
|
||||
* and restores them afterwards.
|
||||
*
|
||||
* For example, if mask is 7, then this scanner will clear the bottom
|
||||
* three bits of each word before fixing.
|
||||
*
|
||||
* This scanner is useful when all words in the area must be treated
|
||||
* as references no matter what tag they have.
|
||||
*/
|
||||
|
||||
mps_res_t mps_scan_area_masked(mps_ss_t ss,
|
||||
void *base, void *limit,
|
||||
void *closure)
|
||||
{
|
||||
mps_scan_tag_t tag = closure;
|
||||
mps_word_t mask = tag->mask;
|
||||
|
||||
MPS_SCAN_AREA(1);
|
||||
|
||||
return MPS_RES_OK;
|
||||
}
|
||||
|
||||
|
||||
/* mps_scan_area_tagged -- scan area selecting by tag
|
||||
*
|
||||
* Like mps_scan_area_masked, except only references whose masked bits
|
||||
* match a particular tag pattern are fixed.
|
||||
*
|
||||
* For example, if mask is 7 and pattern is 5, then this scanner will
|
||||
* only fix words whose low order bits are 0b101.
|
||||
*/
|
||||
|
||||
mps_res_t mps_scan_area_tagged(mps_ss_t ss,
|
||||
void *base, void *limit,
|
||||
void *closure)
|
||||
{
|
||||
mps_scan_tag_t tag = closure;
|
||||
mps_word_t mask = tag->mask;
|
||||
mps_word_t pattern = tag->pattern;
|
||||
|
||||
MPS_SCAN_AREA(tag_bits == pattern);
|
||||
|
||||
return MPS_RES_OK;
|
||||
}
|
||||
|
||||
|
||||
/* mps_scan_area_tagged_or_zero -- scan area selecting by tag or zero
|
||||
*
|
||||
* Like mps_scan_area_tagged, except references whose masked bits are
|
||||
* zero are fixed in addition to those that match the pattern.
|
||||
*
|
||||
* For example, if mask is 7 and pattern is 3, then this scanner will
|
||||
* fix words whose low order bits are 0b011 and words whose low order
|
||||
* bits are 0b000, but not any others.
|
||||
*
|
||||
* This scanner is most useful for ambiguously scanning the stack and
|
||||
* registers when using an optimising C compiler and non-zero tags on
|
||||
* references, since the compiler is likely to leave untagged
|
||||
* addresses of objects around which must not be ignored.
|
||||
*/
|
||||
|
||||
mps_res_t mps_scan_area_tagged_or_zero(mps_ss_t ss,
|
||||
void *base, void *limit,
|
||||
void *closure)
|
||||
{
|
||||
mps_scan_tag_t tag = closure;
|
||||
mps_word_t mask = tag->mask;
|
||||
mps_word_t pattern = tag->pattern;
|
||||
|
||||
MPS_SCAN_AREA(tag_bits == 0 || tag_bits == pattern);
|
||||
|
||||
return MPS_RES_OK;
|
||||
}
|
||||
|
||||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2016 Ravenbrook Limited
|
||||
* <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Redistributions in any form must be accompanied by information on how
|
||||
* to obtain complete source code for this software and any accompanying
|
||||
* software that uses this software. The source code must either be
|
||||
* included in the distribution or be available for no more than the cost
|
||||
* of distribution plus a nominal fee, and must be freely redistributable
|
||||
* under reasonable conditions. For an executable file, complete source
|
||||
* code means the source code for all modules it contains. It does not
|
||||
* include source code for modules or files that typically accompany the
|
||||
* major components of the operating system on which the executable file
|
||||
* runs.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
/* segsmss.c: Segment splitting and merging stress test
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license.
|
||||
* Portions copyright (c) 2002 Global Graphics Software.
|
||||
*
|
||||
* .design: Adapted from amsss.c (because AMS already supports
|
||||
|
|
@ -17,7 +17,7 @@
|
|||
#include "fmtdytst.h"
|
||||
#include "testlib.h"
|
||||
#include "mpslib.h"
|
||||
#include "chain.h"
|
||||
#include "locus.h"
|
||||
#include "mpscams.h"
|
||||
#include "mpsavm.h"
|
||||
#include "mpstd.h"
|
||||
|
|
@ -885,7 +885,7 @@ int main(int argc, char *argv[])
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (c) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -24,20 +24,24 @@ SRCID(ss, "$Id$");
|
|||
* scanning.
|
||||
*/
|
||||
|
||||
Res StackScanInner(ScanState ss,
|
||||
Addr *stackBot,
|
||||
Addr *stackTop,
|
||||
Count nSavedRegs)
|
||||
Res StackScanInner(ScanState ss, Word *stackCold, Word *stackHot,
|
||||
Count nSavedRegs,
|
||||
mps_area_scan_t scan_area, void *closure)
|
||||
{
|
||||
Arena arena;
|
||||
Res res;
|
||||
|
||||
AVERT(ScanState, ss);
|
||||
AVER(stackTop < stackBot);
|
||||
AVER(AddrIsAligned((Addr)stackTop, sizeof(Addr))); /* .assume.align */
|
||||
AVER(0 < nSavedRegs);
|
||||
AVER(nSavedRegs < 128); /* sanity check */
|
||||
|
||||
/* .assume.stack: This implementation assumes that the stack grows
|
||||
* downwards, so that the address of the jmp_buf is the base of the
|
||||
* part of the stack that needs to be scanned. (StackScanInner makes
|
||||
* the same assumption.)
|
||||
*/
|
||||
AVER(stackHot < stackCold);
|
||||
|
||||
arena = ss->arena;
|
||||
|
||||
/* If a stack pointer was stored when we entered the arena (through the
|
||||
|
|
@ -47,16 +51,19 @@ Res StackScanInner(ScanState ss,
|
|||
(trans.c). Otherwise, scan the whole stack. */
|
||||
|
||||
if (arena->stackAtArenaEnter != NULL) {
|
||||
AVER(stackTop < arena->stackAtArenaEnter);
|
||||
AVER(arena->stackAtArenaEnter < stackBot);
|
||||
res = TraceScanAreaTagged(ss, stackTop, stackTop + nSavedRegs);
|
||||
AVER(stackHot < arena->stackAtArenaEnter); /* .assume.stack */
|
||||
AVER(arena->stackAtArenaEnter < stackCold); /* .assume.stack */
|
||||
res = TraceScanArea(ss, stackHot, stackHot + nSavedRegs,
|
||||
scan_area, closure);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
res = TraceScanAreaTagged(ss, arena->stackAtArenaEnter, stackBot);
|
||||
res = TraceScanArea(ss, arena->stackAtArenaEnter, stackCold,
|
||||
scan_area, closure);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
} else {
|
||||
res = TraceScanAreaTagged(ss, stackTop, stackBot);
|
||||
res = TraceScanArea(ss, stackHot, stackCold,
|
||||
scan_area, closure);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,31 +14,29 @@
|
|||
|
||||
/* StackScan -- scan the current thread's stack
|
||||
*
|
||||
* StackScan scans the stack of the current thread, Between stackBot and the
|
||||
* current top of stack. It also fixes any roots which may be in callee-save
|
||||
* registers.
|
||||
* StackScan scans the stack of the current thread, Between stackCold
|
||||
* and the current hot end of the stack. It also fixes any roots which
|
||||
* may be in callee-save registers.
|
||||
*
|
||||
* See the specific implementation for the exact registers which are scanned.
|
||||
*
|
||||
* If a stack pointer has been stashed at arena entry (through the MPS
|
||||
* interface in mpsi*.c) then only the registers and the stack between
|
||||
* stackAtArenaEnter and stackBot is scanned, to avoid scanning false
|
||||
* stackAtArenaEnter and stackCold is scanned, to avoid scanning false
|
||||
* ambiguous references on the MPS's own stack. This is particularly
|
||||
* important for transforms (trans.c).
|
||||
*
|
||||
* The word pointed to by stackBot is fixed if the stack is by convention
|
||||
* The word pointed to by stackCold is fixed if the stack is by convention
|
||||
* empty, and not fixed if it is full. Where empty means sp points to first
|
||||
* free word beyond the top of stack. Full means sp points to the top of
|
||||
* stack itself.
|
||||
*/
|
||||
|
||||
extern Res StackScan(ScanState ss, Addr *stackBot);
|
||||
|
||||
|
||||
extern Res StackScanInner(ScanState ss,
|
||||
Addr *stackBot,
|
||||
Addr *stackTop,
|
||||
Count nSavedRegs);
|
||||
extern Res StackScan(ScanState ss, Word *stackCold,
|
||||
mps_area_scan_t scan_area, void *closure);
|
||||
extern Res StackScanInner(ScanState ss, Word *stackCold, Word *stackHot,
|
||||
Count nSavedRegs,
|
||||
mps_area_scan_t scan_area, void *closure);
|
||||
|
||||
#endif /* ss_h */
|
||||
|
||||
|
|
|
|||
|
|
@ -21,21 +21,17 @@
|
|||
SRCID(ssan, "$Id$");
|
||||
|
||||
|
||||
Res StackScan(ScanState ss, Addr *stackBot)
|
||||
Res StackScan(ScanState ss, Word *stackCold,
|
||||
mps_area_scan_t scan_area,
|
||||
void *closure)
|
||||
{
|
||||
jmp_buf jb;
|
||||
void *stackTop = &jb;
|
||||
|
||||
/* .assume.stack: This implementation assumes that the stack grows
|
||||
* downwards, so that the address of the jmp_buf is the limit of the
|
||||
* part of the stack that needs to be scanned. (StackScanInner makes
|
||||
* the same assumption.)
|
||||
*/
|
||||
AVER(stackTop < (void *)stackBot);
|
||||
Word *stackHot = (void *)&jb;
|
||||
|
||||
(void)setjmp(jb);
|
||||
|
||||
return StackScanInner(ss, stackBot, stackTop, sizeof jb / sizeof(Addr*));
|
||||
return StackScanInner(ss, stackCold, stackHot, sizeof jb / sizeof(Word),
|
||||
scan_area, closure);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -49,9 +49,11 @@ SRCID(ssixi3, "$Id$");
|
|||
#define ASMV(x) __asm__ volatile (x)
|
||||
|
||||
|
||||
Res StackScan(ScanState ss, Addr *stackBot)
|
||||
Res StackScan(ScanState ss, Word *stackCold,
|
||||
mps_area_scan_t scan_area,
|
||||
void *closure)
|
||||
{
|
||||
Addr calleeSaveRegs[4];
|
||||
Word calleeSaveRegs[4];
|
||||
|
||||
/* .assume.asm.stack */
|
||||
/* Store the callee save registers on the stack so they get scanned
|
||||
|
|
@ -62,7 +64,8 @@ Res StackScan(ScanState ss, Addr *stackBot)
|
|||
ASMV("mov %%edi, %0" : "=m" (calleeSaveRegs[2]));
|
||||
ASMV("mov %%ebp, %0" : "=m" (calleeSaveRegs[3]));
|
||||
|
||||
return StackScanInner(ss, stackBot, calleeSaveRegs, NELEMS(calleeSaveRegs));
|
||||
return StackScanInner(ss, stackCold, calleeSaveRegs, NELEMS(calleeSaveRegs),
|
||||
scan_area, closure);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -47,9 +47,11 @@ SRCID(ssixi6, "$Id$");
|
|||
#define ASMV(x) __asm__ volatile (x)
|
||||
|
||||
|
||||
Res StackScan(ScanState ss, Addr *stackBot)
|
||||
Res StackScan(ScanState ss, Word *stackCold,
|
||||
mps_area_scan_t scan_area,
|
||||
void *closure)
|
||||
{
|
||||
Addr calleeSaveRegs[6];
|
||||
Word calleeSaveRegs[6];
|
||||
|
||||
/* .assume.asm.stack */
|
||||
/* Store the callee save registers on the stack so they get scanned
|
||||
|
|
@ -62,7 +64,8 @@ Res StackScan(ScanState ss, Addr *stackBot)
|
|||
ASMV("mov %%r14, %0" : "=m" (calleeSaveRegs[4]));
|
||||
ASMV("mov %%r15, %0" : "=m" (calleeSaveRegs[5]));
|
||||
|
||||
return StackScanInner(ss, stackBot, calleeSaveRegs, NELEMS(calleeSaveRegs));
|
||||
return StackScanInner(ss, stackCold, calleeSaveRegs, NELEMS(calleeSaveRegs),
|
||||
scan_area, closure);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,9 @@
|
|||
SRCID(ssw3i3mv, "$Id$");
|
||||
|
||||
|
||||
Res StackScan(ScanState ss, Addr *stackBot)
|
||||
Res StackScan(ScanState ss, Word *stackCold,
|
||||
mps_area_scan_t scan_area,
|
||||
void *closure)
|
||||
{
|
||||
jmp_buf jb;
|
||||
|
||||
|
|
@ -33,16 +35,17 @@ Res StackScan(ScanState ss, Addr *stackBot)
|
|||
/* These checks will just serve to warn us at compile-time if the
|
||||
setjmp.h header changes to indicate that the registers we want aren't
|
||||
saved any more. */
|
||||
AVER(sizeof(((_JUMP_BUFFER *)jb)->Edi) == sizeof(Addr));
|
||||
AVER(sizeof(((_JUMP_BUFFER *)jb)->Esi) == sizeof(Addr));
|
||||
AVER(sizeof(((_JUMP_BUFFER *)jb)->Ebx) == sizeof(Addr));
|
||||
AVER(sizeof(((_JUMP_BUFFER *)jb)->Ebx) == sizeof(Word));
|
||||
AVER(sizeof(((_JUMP_BUFFER *)jb)->Edi) == sizeof(Word));
|
||||
AVER(sizeof(((_JUMP_BUFFER *)jb)->Esi) == sizeof(Word));
|
||||
|
||||
/* Ensure that the callee-save registers will be found by
|
||||
StackScanInner when it's passed the address of the Ebx field. */
|
||||
AVER(offsetof(_JUMP_BUFFER, Edi) == offsetof(_JUMP_BUFFER, Ebx) + 4);
|
||||
AVER(offsetof(_JUMP_BUFFER, Esi) == offsetof(_JUMP_BUFFER, Ebx) + 8);
|
||||
|
||||
return StackScanInner(ss, stackBot, (Addr *)&((_JUMP_BUFFER *)jb)->Ebx, 3);
|
||||
return StackScanInner(ss, stackCold, (Word *)&((_JUMP_BUFFER *)jb)->Ebx, 3,
|
||||
scan_area, closure);
|
||||
}
|
||||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
|
|
|
|||
|
|
@ -46,19 +46,29 @@ typedef struct __JUMP_BUFFER {
|
|||
} _JUMP_BUFFER;
|
||||
|
||||
|
||||
Res StackScan(ScanState ss, Addr *stackBot)
|
||||
Res StackScan(ScanState ss, Word *stackCold,
|
||||
mps_area_scan_t scan_area,
|
||||
void *closure)
|
||||
{
|
||||
jmp_buf jb;
|
||||
|
||||
/* .assume.ms-compat */
|
||||
(void)setjmp(jb);
|
||||
|
||||
/* These checks, on the _JUMP_BUFFER defined above, are mainly here
|
||||
* to maintain similarity to the matching code on the MPS_BUILD_MV
|
||||
* version of this code. */
|
||||
AVER(sizeof(((_JUMP_BUFFER *)jb)->Ebx) == sizeof(Word));
|
||||
AVER(sizeof(((_JUMP_BUFFER *)jb)->Edi) == sizeof(Word));
|
||||
AVER(sizeof(((_JUMP_BUFFER *)jb)->Esi) == sizeof(Word));
|
||||
|
||||
/* Ensure that the callee-save registers will be found by
|
||||
StackScanInner when it's passed the address of the Ebx field. */
|
||||
AVER(offsetof(_JUMP_BUFFER, Edi) == offsetof(_JUMP_BUFFER, Ebx) + 4);
|
||||
AVER(offsetof(_JUMP_BUFFER, Esi) == offsetof(_JUMP_BUFFER, Ebx) + 8);
|
||||
|
||||
return StackScanInner(ss, stackBot, (Addr *)&((_JUMP_BUFFER *)jb)->Ebx, 3);
|
||||
return StackScanInner(ss, stackCold, (Word *)&((_JUMP_BUFFER *)jb)->Ebx, 3,
|
||||
scan_area, closure);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -30,7 +30,8 @@
|
|||
SRCID(ssw3i6mv, "$Id$");
|
||||
|
||||
|
||||
Res StackScan(ScanState ss, Addr *stackBot)
|
||||
Res StackScan(ScanState ss, Word *stackCold,
|
||||
mps_area_scan_t scan_area, void *closure)
|
||||
{
|
||||
jmp_buf jb;
|
||||
|
||||
|
|
@ -41,13 +42,15 @@ Res StackScan(ScanState ss, Addr *stackBot)
|
|||
/* These checks will just serve to warn us at compile-time if the
|
||||
setjmp.h header changes to indicate that the registers we want aren't
|
||||
saved any more. */
|
||||
AVER(sizeof(((_JUMP_BUFFER *)jb)->Rdi) == sizeof(Addr));
|
||||
AVER(sizeof(((_JUMP_BUFFER *)jb)->Rsi) == sizeof(Addr));
|
||||
AVER(sizeof(((_JUMP_BUFFER *)jb)->Rbp) == sizeof(Addr));
|
||||
AVER(sizeof(((_JUMP_BUFFER *)jb)->R12) == sizeof(Addr));
|
||||
AVER(sizeof(((_JUMP_BUFFER *)jb)->R13) == sizeof(Addr));
|
||||
AVER(sizeof(((_JUMP_BUFFER *)jb)->R14) == sizeof(Addr));
|
||||
AVER(sizeof(((_JUMP_BUFFER *)jb)->R15) == sizeof(Addr));
|
||||
AVER(sizeof(((_JUMP_BUFFER *)jb)->Rbx) == sizeof(Word));
|
||||
AVER(sizeof(((_JUMP_BUFFER *)jb)->Rsp) == sizeof(Word));
|
||||
AVER(sizeof(((_JUMP_BUFFER *)jb)->Rbp) == sizeof(Word));
|
||||
AVER(sizeof(((_JUMP_BUFFER *)jb)->Rsi) == sizeof(Word));
|
||||
AVER(sizeof(((_JUMP_BUFFER *)jb)->Rdi) == sizeof(Word));
|
||||
AVER(sizeof(((_JUMP_BUFFER *)jb)->R12) == sizeof(Word));
|
||||
AVER(sizeof(((_JUMP_BUFFER *)jb)->R13) == sizeof(Word));
|
||||
AVER(sizeof(((_JUMP_BUFFER *)jb)->R14) == sizeof(Word));
|
||||
AVER(sizeof(((_JUMP_BUFFER *)jb)->R15) == sizeof(Word));
|
||||
|
||||
/* The layout of the jmp_buf forces us to harmlessly scan Rsp as well. */
|
||||
AVER(offsetof(_JUMP_BUFFER, Rsp) == offsetof(_JUMP_BUFFER, Rbx) + 8);
|
||||
|
|
@ -59,7 +62,8 @@ Res StackScan(ScanState ss, Addr *stackBot)
|
|||
AVER(offsetof(_JUMP_BUFFER, R14) == offsetof(_JUMP_BUFFER, Rbx) + 56);
|
||||
AVER(offsetof(_JUMP_BUFFER, R15) == offsetof(_JUMP_BUFFER, Rbx) + 64);
|
||||
|
||||
return StackScanInner(ss, stackBot, (Addr *)&((_JUMP_BUFFER *)jb)->Rbx, 9);
|
||||
return StackScanInner(ss, stackCold, (Word *)&((_JUMP_BUFFER *)jb)->Rbx, 9,
|
||||
scan_area, closure);
|
||||
}
|
||||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ typedef struct _JUMP_BUFFER {
|
|||
} _JUMP_BUFFER;
|
||||
|
||||
|
||||
Res StackScan(ScanState ss, Addr *stackBot)
|
||||
Res StackScan(ScanState ss, Word *stackCold, Word mask, Word pattern)
|
||||
{
|
||||
jmp_buf jb;
|
||||
|
||||
|
|
@ -76,16 +76,18 @@ Res StackScan(ScanState ss, Addr *stackBot)
|
|||
registers in the jmp_buf. */
|
||||
(void)setjmp(jb);
|
||||
|
||||
/* These checks will just serve to warn us at compile-time if the
|
||||
setjmp.h header changes to indicate that the registers we want aren't
|
||||
saved any more. */
|
||||
AVER(sizeof(((_JUMP_BUFFER *)jb)->Rdi) == sizeof(Addr));
|
||||
AVER(sizeof(((_JUMP_BUFFER *)jb)->Rsi) == sizeof(Addr));
|
||||
AVER(sizeof(((_JUMP_BUFFER *)jb)->Rbp) == sizeof(Addr));
|
||||
AVER(sizeof(((_JUMP_BUFFER *)jb)->R12) == sizeof(Addr));
|
||||
AVER(sizeof(((_JUMP_BUFFER *)jb)->R13) == sizeof(Addr));
|
||||
AVER(sizeof(((_JUMP_BUFFER *)jb)->R14) == sizeof(Addr));
|
||||
AVER(sizeof(((_JUMP_BUFFER *)jb)->R15) == sizeof(Addr));
|
||||
/* These checks, on the _JUMP_BUFFER defined above, are mainly here
|
||||
* to maintain similarity to the matching code on the MPS_BUILD_MV
|
||||
* version of this code. */
|
||||
AVER(sizeof(((_JUMP_BUFFER *)jb)->Rbx) == sizeof(Word));
|
||||
AVER(sizeof(((_JUMP_BUFFER *)jb)->Rsp) == sizeof(Word));
|
||||
AVER(sizeof(((_JUMP_BUFFER *)jb)->Rbp) == sizeof(Word));
|
||||
AVER(sizeof(((_JUMP_BUFFER *)jb)->Rsi) == sizeof(Word));
|
||||
AVER(sizeof(((_JUMP_BUFFER *)jb)->Rdi) == sizeof(Word));
|
||||
AVER(sizeof(((_JUMP_BUFFER *)jb)->R12) == sizeof(Word));
|
||||
AVER(sizeof(((_JUMP_BUFFER *)jb)->R13) == sizeof(Word));
|
||||
AVER(sizeof(((_JUMP_BUFFER *)jb)->R14) == sizeof(Word));
|
||||
AVER(sizeof(((_JUMP_BUFFER *)jb)->R15) == sizeof(Word));
|
||||
|
||||
/* The layout of the jmp_buf forces us to harmlessly scan Rsp as well. */
|
||||
AVER(offsetof(_JUMP_BUFFER, Rsp) == offsetof(_JUMP_BUFFER, Rbx) + 8);
|
||||
|
|
@ -97,7 +99,8 @@ Res StackScan(ScanState ss, Addr *stackBot)
|
|||
AVER(offsetof(_JUMP_BUFFER, R14) == offsetof(_JUMP_BUFFER, Rbx) + 56);
|
||||
AVER(offsetof(_JUMP_BUFFER, R15) == offsetof(_JUMP_BUFFER, Rbx) + 64);
|
||||
|
||||
return StackScanInner(ss, stackBot, (Addr *)&((_JUMP_BUFFER *)jb)->Rbx, 9);
|
||||
return StackScanInner(ss, stackCold, (Word *)&((_JUMP_BUFFER *)jb)->Rbx, 9,
|
||||
mask, pattern);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
307
mps/code/tagtest.c
Normal file
307
mps/code/tagtest.c
Normal file
|
|
@ -0,0 +1,307 @@
|
|||
/* tagtest.c: TAGGED POINTER TEST
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2015 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* .overview: This test case checks that the MPS correctly handles
|
||||
* tagged pointers via the object format and tagged area scanning.
|
||||
*/
|
||||
|
||||
#include <stdio.h> /* printf */
|
||||
|
||||
#include "mpm.h"
|
||||
#include "mps.h"
|
||||
#include "mpsavm.h"
|
||||
#include "mpscamc.h"
|
||||
#include "testlib.h"
|
||||
|
||||
#define OBJCOUNT 1000 /* Number of conses to allocate */
|
||||
|
||||
typedef struct cons_s {
|
||||
mps_word_t car, cdr;
|
||||
} cons_s, *cons_t;
|
||||
|
||||
typedef mps_word_t imm_t; /* Immediate value. */
|
||||
typedef mps_word_t fwd_t; /* Fowarding pointer. */
|
||||
|
||||
static mps_word_t tag_bits; /* Number of tag bits */
|
||||
static mps_word_t tag_cons; /* Tag bits indicating pointer to cons */
|
||||
static mps_word_t tag_fwd; /* Tag bits indicating forwarding pointer */
|
||||
static mps_word_t tag_imm; /* Tag bits indicating immediate value */
|
||||
static mps_word_t tag_invalid; /* Invalid tag bits */
|
||||
static mps_addr_t refs[OBJCOUNT]; /* Tagged references to objects */
|
||||
|
||||
#define TAG_COUNT ((mps_word_t)1 << tag_bits) /* Number of distinct tags */
|
||||
#define TAG_MASK (TAG_COUNT - 1) /* Tag mask */
|
||||
#define TAG(word) ((mps_word_t)(word) & TAG_MASK)
|
||||
#define TAGGED(value, type) (((mps_word_t)(value) & ~TAG_MASK) + tag_ ## type)
|
||||
#define UNTAGGED(word, type) ((type ## _t)((mps_word_t)(word) & ~TAG_MASK))
|
||||
|
||||
static mps_word_t make_cons(mps_ap_t ap, mps_word_t car, mps_word_t cdr)
|
||||
{
|
||||
cons_t obj;
|
||||
mps_addr_t addr;
|
||||
size_t size = sizeof(cons_s);
|
||||
do {
|
||||
mps_res_t res = mps_reserve(&addr, ap, size);
|
||||
if (res != MPS_RES_OK) error("out of memory in cons");
|
||||
obj = addr;
|
||||
obj->car = car;
|
||||
obj->cdr = cdr;
|
||||
} while (!mps_commit(ap, addr, size));
|
||||
return TAGGED(obj, cons);
|
||||
}
|
||||
|
||||
static void fwd(mps_addr_t old, mps_addr_t new)
|
||||
{
|
||||
cons_t cons = old;
|
||||
cons->car = TAGGED(0, fwd);
|
||||
cons->cdr = (mps_word_t)new;
|
||||
}
|
||||
|
||||
static mps_addr_t isfwd(mps_addr_t addr)
|
||||
{
|
||||
cons_t cons = addr;
|
||||
if (TAG(cons->car) != tag_fwd)
|
||||
return NULL;
|
||||
return (mps_addr_t)cons->cdr;
|
||||
}
|
||||
|
||||
static void pad(mps_addr_t addr, size_t size)
|
||||
{
|
||||
mps_word_t *word = addr;
|
||||
mps_word_t *limit = (mps_word_t *)((char *)addr + size);
|
||||
while (word < limit) {
|
||||
*word = TAGGED(0, imm);
|
||||
++ word;
|
||||
}
|
||||
}
|
||||
|
||||
static mps_res_t scan(mps_ss_t ss, mps_addr_t base,
|
||||
mps_addr_t limit)
|
||||
{
|
||||
MPS_SCAN_BEGIN(ss) {
|
||||
mps_word_t *p = base;
|
||||
while (p < (mps_word_t *)limit) {
|
||||
mps_word_t word = *p;
|
||||
mps_word_t tag = TAG(word);
|
||||
if (tag == tag_cons) {
|
||||
mps_addr_t ref = UNTAGGED(word, cons);
|
||||
if (MPS_FIX1(ss, ref)) {
|
||||
mps_res_t res = MPS_FIX2(ss, &ref);
|
||||
if (res != MPS_RES_OK)
|
||||
return res;
|
||||
*p = TAGGED(ref, cons);
|
||||
}
|
||||
}
|
||||
++p;
|
||||
}
|
||||
} MPS_SCAN_END(ss);
|
||||
return MPS_RES_OK;
|
||||
}
|
||||
|
||||
static mps_addr_t skip(mps_addr_t addr)
|
||||
{
|
||||
return (mps_addr_t)((char *)addr + sizeof(cons_s));
|
||||
}
|
||||
|
||||
|
||||
static void collect(mps_arena_t arena, size_t expected)
|
||||
{
|
||||
size_t finalized = 0;
|
||||
mps_arena_collect(arena);
|
||||
while (mps_message_poll(arena)) {
|
||||
mps_message_t message;
|
||||
mps_addr_t objaddr;
|
||||
cdie(mps_message_get(&message, arena, mps_message_type_finalization()),
|
||||
"message_get");
|
||||
mps_message_finalization_ref(&objaddr, arena, message);
|
||||
Insist(TAG(objaddr) == 0);
|
||||
mps_message_discard(arena, message);
|
||||
++ finalized;
|
||||
}
|
||||
printf("finalized=%lu expected=%lu\n",
|
||||
(unsigned long)finalized, (unsigned long)expected);
|
||||
Insist(finalized == expected);
|
||||
}
|
||||
|
||||
|
||||
/* test -- Run the test case in the specified mode. */
|
||||
|
||||
#define MODES(R, X) \
|
||||
R(X, CONS, "Scan words tagged \"cons\".") \
|
||||
R(X, INVALID, "Scan words tagged \"invalid\".")
|
||||
|
||||
#define MODES_ENUM(X, id, comment) MODE_ ## id,
|
||||
|
||||
enum {
|
||||
MODES(MODES_ENUM, X)
|
||||
MODE_LIMIT
|
||||
};
|
||||
|
||||
#define MODES_NAME(X, id, comment) #id,
|
||||
|
||||
static const char *mode_name[] = {
|
||||
MODES(MODES_NAME, X)
|
||||
};
|
||||
|
||||
|
||||
static void test(int mode)
|
||||
{
|
||||
mps_arena_t arena;
|
||||
mps_thr_t thread;
|
||||
mps_root_t root;
|
||||
mps_fmt_t fmt;
|
||||
mps_pool_t pool;
|
||||
mps_ap_t ap;
|
||||
size_t expected = 0;
|
||||
size_t i;
|
||||
|
||||
printf("test(%s)\n", mode_name[mode]);
|
||||
|
||||
die(mps_arena_create(&arena, mps_arena_class_vm(), mps_args_none), "arena");
|
||||
mps_message_type_enable(arena, mps_message_type_finalization());
|
||||
die(mps_thread_reg(&thread, arena), "thread");
|
||||
|
||||
switch (mode) {
|
||||
default:
|
||||
Insist(0);
|
||||
/* fall through */
|
||||
case MODE_CONS:
|
||||
/* Scan words tagged "cons" -- everything will live. */
|
||||
die(mps_root_create_area_tagged(&root, arena, mps_rank_ambig(), 0,
|
||||
refs, refs + OBJCOUNT,
|
||||
mps_scan_area_tagged, TAG_MASK, tag_cons),
|
||||
"root");
|
||||
expected = 0;
|
||||
break;
|
||||
case MODE_INVALID:
|
||||
/* Scan words tagged "invalid" -- everything will die. */
|
||||
die(mps_root_create_area_tagged(&root, arena, mps_rank_ambig(), 0,
|
||||
refs, refs + OBJCOUNT,
|
||||
mps_scan_area_tagged, TAG_MASK, tag_invalid),
|
||||
"root");
|
||||
expected = OBJCOUNT;
|
||||
break;
|
||||
}
|
||||
|
||||
MPS_ARGS_BEGIN(args) {
|
||||
MPS_ARGS_ADD(args, MPS_KEY_FMT_SCAN, scan);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_FMT_SKIP, skip);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_FMT_FWD, fwd);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_FMT_ISFWD, isfwd);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_FMT_PAD, pad);
|
||||
die(mps_fmt_create_k(&fmt, arena, args), "fmt");
|
||||
} MPS_ARGS_END(args);
|
||||
|
||||
MPS_ARGS_BEGIN(args) {
|
||||
MPS_ARGS_ADD(args, MPS_KEY_FORMAT, fmt);
|
||||
die(mps_pool_create_k(&pool, arena, mps_class_amc(), args), "pool");
|
||||
} MPS_ARGS_END(args);
|
||||
|
||||
die(mps_ap_create_k(&ap, pool, mps_args_none), "ap");
|
||||
|
||||
for (i = 0; i < OBJCOUNT; ++i) {
|
||||
mps_word_t p, r;
|
||||
mps_word_t q = TAGGED(i << tag_bits, imm);
|
||||
mps_addr_t addr;
|
||||
p = make_cons(ap, q, q);
|
||||
Insist(TAG(p) == tag_cons);
|
||||
r = TAGGED(p, imm);
|
||||
UNTAGGED(p, cons)->cdr = r;
|
||||
refs[i] = (mps_addr_t)p;
|
||||
addr = (mps_addr_t)UNTAGGED(p, cons);
|
||||
die(mps_finalize(arena, &addr), "finalize");
|
||||
}
|
||||
|
||||
collect(arena, expected);
|
||||
|
||||
mps_arena_park(arena);
|
||||
mps_ap_destroy(ap);
|
||||
mps_pool_destroy(pool);
|
||||
mps_fmt_destroy(fmt);
|
||||
mps_root_destroy(root);
|
||||
mps_thread_dereg(thread);
|
||||
mps_arena_destroy(arena);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
mps_word_t tags[sizeof(mps_word_t)];
|
||||
size_t i;
|
||||
int mode;
|
||||
|
||||
testlib_init(argc, argv);
|
||||
|
||||
/* Work out how many tags to use. */
|
||||
tag_bits = SizeLog2(sizeof(mps_word_t));
|
||||
Insist(TAG_COUNT <= NELEMS(tags));
|
||||
|
||||
/* Shuffle the tags. */
|
||||
for (i = 0; i < TAG_COUNT; ++i) {
|
||||
tags[i] = i;
|
||||
}
|
||||
for (i = 0; i < TAG_COUNT; ++i) {
|
||||
size_t j = i + rnd() % (TAG_COUNT - i);
|
||||
mps_word_t t = tags[i];
|
||||
tags[i] = tags[j];
|
||||
tags[j] = t;
|
||||
}
|
||||
tag_cons = tags[0];
|
||||
tag_fwd = tags[1];
|
||||
tag_imm = tags[2];
|
||||
tag_invalid = tags[3];
|
||||
|
||||
printf("tags: cons = %u, fwd = %u, imm = %u, invalid = %u\n",
|
||||
(unsigned)tag_cons, (unsigned)tag_fwd,
|
||||
(unsigned)tag_imm, (unsigned)tag_invalid);
|
||||
|
||||
for (mode = 0; mode < MODE_LIMIT; ++mode) {
|
||||
test(mode);
|
||||
}
|
||||
|
||||
printf("%s: Conclusion: Failed to find any defects.\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (c) 2015 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Redistributions in any form must be accompanied by information on how
|
||||
* to obtain complete source code for this software and any accompanying
|
||||
* software that uses this software. The source code must either be
|
||||
* included in the distribution or be available for no more than the cost
|
||||
* of distribution plus a nominal fee, and must be freely redistributable
|
||||
* under reasonable conditions. For an executable file, complete source
|
||||
* code means the source code for all modules it contains. It does not
|
||||
* include source code for modules or files that typically accompany the
|
||||
* major components of the operating system on which the executable file
|
||||
* runs.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
|
@ -47,9 +47,13 @@
|
|||
*/
|
||||
#define ATTRIBUTE_FORMAT(ARGLIST) __attribute__((__format__ ARGLIST))
|
||||
|
||||
/* GCC: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html */
|
||||
#define ATTRIBUTE_NOINLINE __attribute__((__noinline__))
|
||||
|
||||
#else
|
||||
|
||||
#define ATTRIBUTE_FORMAT(ARGLIST)
|
||||
#define ATTRIBUTE_NOINLINE
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -68,7 +68,9 @@ extern Thread ThreadRingThread(Ring threadRing);
|
|||
|
||||
extern Arena ThreadArena(Thread thread);
|
||||
|
||||
extern Res ThreadScan(ScanState ss, Thread thread, void *stackBot);
|
||||
extern Res ThreadScan(ScanState ss, Thread thread, Word *stackCold,
|
||||
mps_area_scan_t scan_area,
|
||||
void *closure);
|
||||
|
||||
|
||||
#endif /* th_h */
|
||||
|
|
|
|||
|
|
@ -117,10 +117,12 @@ Arena ThreadArena(Thread thread)
|
|||
}
|
||||
|
||||
|
||||
Res ThreadScan(ScanState ss, Thread thread, void *stackBot)
|
||||
Res ThreadScan(ScanState ss, Thread thread, Word *stackCold,
|
||||
mps_area_scan_t scan_area,
|
||||
void *closure)
|
||||
{
|
||||
UNUSED(thread);
|
||||
return StackScan(ss, stackBot);
|
||||
return StackScan(ss, stackCold, scan_area, closure);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -239,7 +239,9 @@ Arena ThreadArena(Thread thread)
|
|||
|
||||
/* ThreadScan -- scan the state of a thread (stack and regs) */
|
||||
|
||||
Res ThreadScan(ScanState ss, Thread thread, void *stackBot)
|
||||
Res ThreadScan(ScanState ss, Thread thread, Word *stackCold,
|
||||
mps_area_scan_t scan_area,
|
||||
void *closure)
|
||||
{
|
||||
pthread_t self;
|
||||
Res res;
|
||||
|
|
@ -249,32 +251,34 @@ Res ThreadScan(ScanState ss, Thread thread, void *stackBot)
|
|||
if(pthread_equal(self, thread->id)) {
|
||||
/* scan this thread's stack */
|
||||
AVER(thread->alive);
|
||||
res = StackScan(ss, stackBot);
|
||||
res = StackScan(ss, stackCold, scan_area, closure);
|
||||
if(res != ResOK)
|
||||
return res;
|
||||
} else if (thread->alive) {
|
||||
MutatorFaultContext mfc;
|
||||
Addr *stackBase, *stackLimit, stackPtr;
|
||||
Word *stackBase, *stackLimit;
|
||||
Addr stackPtr;
|
||||
|
||||
mfc = thread->mfc;
|
||||
AVER(mfc != NULL);
|
||||
|
||||
stackPtr = MutatorFaultContextSP(mfc);
|
||||
/* .stack.align */
|
||||
stackBase = (Addr *)AddrAlignUp(stackPtr, sizeof(Addr));
|
||||
stackLimit = (Addr *)stackBot;
|
||||
stackBase = (Word *)AddrAlignUp(stackPtr, sizeof(Word));
|
||||
stackLimit = stackCold;
|
||||
if (stackBase >= stackLimit)
|
||||
return ResOK; /* .stack.below-bottom */
|
||||
|
||||
/* scan stack inclusive of current sp and exclusive of
|
||||
* stackBot (.stack.full-descend)
|
||||
* stackCold (.stack.full-descend)
|
||||
*/
|
||||
res = TraceScanAreaTagged(ss, stackBase, stackLimit);
|
||||
res = TraceScanArea(ss, stackBase, stackLimit,
|
||||
scan_area, closure);
|
||||
if(res != ResOK)
|
||||
return res;
|
||||
|
||||
/* scan the registers in the mutator fault context */
|
||||
res = MutatorFaultContextScan(ss, mfc);
|
||||
res = MutatorFaultContextScan(ss, mfc, scan_area, closure);
|
||||
if(res != ResOK)
|
||||
return res;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -67,23 +67,19 @@
|
|||
SRCID(thw3i3, "$Id$");
|
||||
|
||||
|
||||
Res ThreadScan(ScanState ss, Thread thread, void *stackBot)
|
||||
Res ThreadScan(ScanState ss, Thread thread, Word *stackCold,
|
||||
mps_area_scan_t scan_area, void *closure)
|
||||
{
|
||||
DWORD id;
|
||||
Res res;
|
||||
|
||||
id = GetCurrentThreadId();
|
||||
|
||||
if (id == thread->id) { /* .thread.id */
|
||||
/* scan this thread's stack */
|
||||
AVER(thread->alive);
|
||||
res = StackScan(ss, stackBot);
|
||||
if(res != ResOK)
|
||||
return res;
|
||||
} else if (thread->alive) {
|
||||
if (id != thread->id) { /* .thread.id */
|
||||
CONTEXT context;
|
||||
BOOL success;
|
||||
Addr *stackBase, *stackLimit, stackPtr;
|
||||
Word *stackBase, *stackLimit;
|
||||
Addr stackPtr;
|
||||
|
||||
/* scan stack and register roots in other threads */
|
||||
|
||||
|
|
@ -101,15 +97,16 @@ Res ThreadScan(ScanState ss, Thread thread, void *stackBot)
|
|||
|
||||
stackPtr = (Addr)context.Esp; /* .i3.sp */
|
||||
/* .stack.align */
|
||||
stackBase = (Addr *)AddrAlignUp(stackPtr, sizeof(Addr));
|
||||
stackLimit = (Addr *)stackBot;
|
||||
stackBase = (Word *)AddrAlignUp(stackPtr, sizeof(Word));
|
||||
stackLimit = stackCold;
|
||||
if (stackBase >= stackLimit)
|
||||
return ResOK; /* .stack.below-bottom */
|
||||
|
||||
/* scan stack inclusive of current sp and exclusive of
|
||||
* stackBot (.stack.full-descend)
|
||||
* stackCold (.stack.full-descend)
|
||||
*/
|
||||
res = TraceScanAreaTagged(ss, stackBase, stackLimit);
|
||||
res = TraceScanArea(ss, stackBase, stackLimit,
|
||||
scan_area, closure);
|
||||
if(res != ResOK)
|
||||
return res;
|
||||
|
||||
|
|
@ -118,8 +115,14 @@ Res ThreadScan(ScanState ss, Thread thread, void *stackBot)
|
|||
* unnecessarily scans the rest of the context. The optimisation
|
||||
* to scan only relevant parts would be machine dependent.
|
||||
*/
|
||||
res = TraceScanAreaTagged(ss, (Addr *)&context,
|
||||
(Addr *)((char *)&context + sizeof(CONTEXT)));
|
||||
res = TraceScanArea(ss, (Word *)&context,
|
||||
(Word *)((char *)&context + sizeof(CONTEXT)),
|
||||
scan_area, closure);
|
||||
if(res != ResOK)
|
||||
return res;
|
||||
|
||||
} else { /* scan this thread's stack */
|
||||
res = StackScan(ss, stackCold, scan_area, closure);
|
||||
if(res != ResOK)
|
||||
return res;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -67,23 +67,20 @@
|
|||
SRCID(thw3i6, "$Id$");
|
||||
|
||||
|
||||
Res ThreadScan(ScanState ss, Thread thread, void *stackBot)
|
||||
Res ThreadScan(ScanState ss, Thread thread, Word *stackCold,
|
||||
mps_area_scan_t scan_area,
|
||||
void *closure)
|
||||
{
|
||||
DWORD id;
|
||||
Res res;
|
||||
|
||||
id = GetCurrentThreadId();
|
||||
|
||||
if (id == thread->id) { /* .thread.id */
|
||||
/* scan this thread's stack */
|
||||
AVER(thread->alive);
|
||||
res = StackScan(ss, stackBot);
|
||||
if(res != ResOK)
|
||||
return res;
|
||||
} else if (thread->alive) {
|
||||
if (id != thread->id) { /* .thread.id */
|
||||
CONTEXT context;
|
||||
BOOL success;
|
||||
Addr *stackBase, *stackLimit, stackPtr;
|
||||
Word *stackBase, *stackLimit;
|
||||
Addr stackPtr;
|
||||
|
||||
/* scan stack and register roots in other threads */
|
||||
|
||||
|
|
@ -101,15 +98,16 @@ Res ThreadScan(ScanState ss, Thread thread, void *stackBot)
|
|||
|
||||
stackPtr = (Addr)context.Rsp; /* .i6.sp */
|
||||
/* .stack.align */
|
||||
stackBase = (Addr *)AddrAlignUp(stackPtr, sizeof(Addr));
|
||||
stackLimit = (Addr *)stackBot;
|
||||
stackBase = (Word *)AddrAlignUp(stackPtr, sizeof(Word));
|
||||
stackLimit = stackCold;
|
||||
if (stackBase >= stackLimit)
|
||||
return ResOK; /* .stack.below-bottom */
|
||||
|
||||
/* scan stack inclusive of current sp and exclusive of
|
||||
* stackBot (.stack.full-descend)
|
||||
* stackCold (.stack.full-descend)
|
||||
*/
|
||||
res = TraceScanAreaTagged(ss, stackBase, stackLimit);
|
||||
res = TraceScanArea(ss, stackBase, stackLimit,
|
||||
scan_area, closure);
|
||||
if(res != ResOK)
|
||||
return res;
|
||||
|
||||
|
|
@ -118,8 +116,14 @@ Res ThreadScan(ScanState ss, Thread thread, void *stackBot)
|
|||
* unnecessarily scans the rest of the context. The optimisation
|
||||
* to scan only relevant parts would be machine dependent.
|
||||
*/
|
||||
res = TraceScanAreaTagged(ss, (Addr *)&context,
|
||||
(Addr *)((char *)&context + sizeof(CONTEXT)));
|
||||
res = TraceScanArea(ss, (Word *)&context,
|
||||
(Word *)((char *)&context + sizeof(CONTEXT)),
|
||||
scan_area, closure);
|
||||
if(res != ResOK)
|
||||
return res;
|
||||
|
||||
} else { /* scan this thread's stack */
|
||||
res = StackScan(ss, stackCold, scan_area, closure);
|
||||
if(res != ResOK)
|
||||
return res;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -210,7 +210,8 @@ Arena ThreadArena(Thread thread)
|
|||
|
||||
#include "prmcxc.h"
|
||||
|
||||
Res ThreadScan(ScanState ss, Thread thread, void *stackBot)
|
||||
Res ThreadScan(ScanState ss, Thread thread, Word *stackCold,
|
||||
mps_area_scan_t scan_area, void *closure)
|
||||
{
|
||||
mach_port_t self;
|
||||
Res res;
|
||||
|
|
@ -221,13 +222,14 @@ Res ThreadScan(ScanState ss, Thread thread, void *stackBot)
|
|||
if (thread->port == self) {
|
||||
/* scan this thread's stack */
|
||||
AVER(thread->alive);
|
||||
res = StackScan(ss, stackBot);
|
||||
res = StackScan(ss, stackCold, scan_area, closure);
|
||||
if(res != ResOK)
|
||||
return res;
|
||||
} else if (thread->alive) {
|
||||
MutatorFaultContextStruct mfcStruct;
|
||||
THREAD_STATE_S threadState;
|
||||
Addr *stackBase, *stackLimit, stackPtr;
|
||||
Word *stackBase, *stackLimit;
|
||||
Addr stackPtr;
|
||||
mach_msg_type_number_t count;
|
||||
kern_return_t kern_return;
|
||||
|
||||
|
|
@ -249,20 +251,21 @@ Res ThreadScan(ScanState ss, Thread thread, void *stackBot)
|
|||
|
||||
stackPtr = MutatorFaultContextSP(&mfcStruct);
|
||||
/* .stack.align */
|
||||
stackBase = (Addr *)AddrAlignUp(stackPtr, sizeof(Addr));
|
||||
stackLimit = (Addr *)stackBot;
|
||||
stackBase = (Word *)AddrAlignUp(stackPtr, sizeof(Word));
|
||||
stackLimit = stackCold;
|
||||
if (stackBase >= stackLimit)
|
||||
return ResOK; /* .stack.below-bottom */
|
||||
|
||||
/* scan stack inclusive of current sp and exclusive of
|
||||
* stackBot (.stack.full-descend)
|
||||
* stackCold (.stack.full-descend)
|
||||
*/
|
||||
res = TraceScanAreaTagged(ss, stackBase, stackLimit);
|
||||
res = TraceScanArea(ss, stackBase, stackLimit,
|
||||
scan_area, closure);
|
||||
if(res != ResOK)
|
||||
return res;
|
||||
|
||||
/* scan the registers in the mutator fault context */
|
||||
res = MutatorFaultContextScan(ss, &mfcStruct);
|
||||
res = MutatorFaultContextScan(ss, &mfcStruct, scan_area, closure);
|
||||
if(res != ResOK)
|
||||
return res;
|
||||
}
|
||||
|
|
|
|||
115
mps/code/trace.c
115
mps/code/trace.c
|
|
@ -1,13 +1,13 @@
|
|||
/* trace.c: GENERIC TRACER IMPLEMENTATION
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2015 Ravenbrook Limited.
|
||||
* Copyright (c) 2001-2016 Ravenbrook Limited.
|
||||
* See end of file for license.
|
||||
* Portions copyright (C) 2002 Global Graphics Software.
|
||||
*
|
||||
* .design: <design/trace/>. */
|
||||
|
||||
#include "chain.h"
|
||||
#include "locus.h"
|
||||
#include "mpm.h"
|
||||
#include <limits.h> /* for LONG_MAX */
|
||||
|
||||
|
|
@ -1420,108 +1420,33 @@ void TraceScanSingleRef(TraceSet ts, Rank rank, Arena arena,
|
|||
}
|
||||
|
||||
|
||||
/* TraceScanArea -- scan contiguous area of references
|
||||
/* TraceScanArea -- scan an area of memory for references
|
||||
*
|
||||
* This is a convenience function for scanning the contiguous area
|
||||
* [base, limit). I.e., it calls Fix on all words from base up to
|
||||
* limit, inclusive of base and exclusive of limit. */
|
||||
* This is a wrapper for area scanning functions, which should not
|
||||
* otherwise be called directly from within the MPS. This function
|
||||
* checks arguments and takes care of accounting for the scanned
|
||||
* memory.
|
||||
*
|
||||
* c.f. FormatScan()
|
||||
*/
|
||||
|
||||
Res TraceScanArea(ScanState ss, Addr *base, Addr *limit)
|
||||
Res TraceScanArea(ScanState ss, Word *base, Word *limit,
|
||||
mps_area_scan_t scan_area,
|
||||
void *closure)
|
||||
{
|
||||
Res res;
|
||||
Addr *p;
|
||||
Ref ref;
|
||||
|
||||
AVERT(ScanState, ss);
|
||||
AVER(base != NULL);
|
||||
AVER(limit != NULL);
|
||||
AVER(base < limit);
|
||||
|
||||
EVENT3(TraceScanArea, ss, base, limit);
|
||||
|
||||
TRACE_SCAN_BEGIN(ss) {
|
||||
p = base;
|
||||
loop:
|
||||
if (p >= limit)
|
||||
goto out;
|
||||
ref = *p++;
|
||||
if(!TRACE_FIX1(ss, ref))
|
||||
goto loop;
|
||||
res = TRACE_FIX2(ss, p-1);
|
||||
if(res == ResOK)
|
||||
goto loop;
|
||||
return res;
|
||||
out:
|
||||
AVER(p == limit);
|
||||
} TRACE_SCAN_END(ss);
|
||||
/* scannedSize is accumulated whether or not scan_area succeeds, so
|
||||
it's safe to accumulate now so that we can tail-call
|
||||
scan_area. */
|
||||
ss->scannedSize += AddrOffset(base, limit);
|
||||
|
||||
return ResOK;
|
||||
}
|
||||
|
||||
|
||||
/* TraceScanAreaTagged -- scan contiguous area of tagged references
|
||||
*
|
||||
* .tagging: This is as TraceScanArea except words are only fixed they are
|
||||
* tagged as zero according to the alignment of a Word.
|
||||
*
|
||||
* See also PoolSingleAccess <code/poolabs.c#.tagging>.
|
||||
*
|
||||
* TODO: Generalise the handling of tags so that pools can decide how
|
||||
* their objects are tagged. This may use the user defined format
|
||||
* to describe how tags are done */
|
||||
Res TraceScanAreaTagged(ScanState ss, Addr *base, Addr *limit)
|
||||
{
|
||||
Word mask;
|
||||
|
||||
/* NOTE: An optimisation that maybe worth considering is setting some of the
|
||||
* top bits in the mask as an early catch of addresses outside the arena.
|
||||
* This might help slightly on 64-bit windows. However these are picked up
|
||||
* soon afterwards by later checks. The bottom bits are more important
|
||||
* to check as we ignore them in AMCFix, so the non-reference could
|
||||
* otherwise end up pinning an object. */
|
||||
mask = sizeof(Word) - 1;
|
||||
AVER(WordIsP2(mask + 1));
|
||||
return TraceScanAreaMasked(ss, base, limit, mask);
|
||||
}
|
||||
|
||||
|
||||
/* TraceScanAreaMasked -- scan contiguous area of filtered references
|
||||
*
|
||||
* This is as TraceScanArea except words are only fixed if they are zero
|
||||
* when masked with a mask. */
|
||||
|
||||
ATTRIBUTE_NO_SANITIZE_ADDRESS
|
||||
Res TraceScanAreaMasked(ScanState ss, Addr *base, Addr *limit, Word mask)
|
||||
{
|
||||
Res res;
|
||||
Addr *p;
|
||||
Ref ref;
|
||||
|
||||
AVERT(ScanState, ss);
|
||||
AVER(base != NULL);
|
||||
AVER(limit != NULL);
|
||||
AVER(base < limit);
|
||||
|
||||
EVENT3(TraceScanAreaTagged, ss, base, limit);
|
||||
|
||||
TRACE_SCAN_BEGIN(ss) {
|
||||
p = base;
|
||||
loop:
|
||||
if (p >= limit)
|
||||
goto out;
|
||||
ref = *p++;
|
||||
if (((Word)ref & mask)
|
||||
!= 0) goto loop;
|
||||
if (!TRACE_FIX1(ss, ref))
|
||||
goto loop;
|
||||
res = TRACE_FIX2(ss, p-1);
|
||||
if(res == ResOK)
|
||||
goto loop;
|
||||
return res;
|
||||
out:
|
||||
AVER(p == limit);
|
||||
} TRACE_SCAN_END(ss);
|
||||
|
||||
return ResOK;
|
||||
return scan_area(&ss->ss_s, base, limit, closure);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1900,7 +1825,7 @@ Res TraceDescribe(Trace trace, mps_lib_FILE *stream, Count depth)
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2015 Ravenbrook Limited
|
||||
* Copyright (C) 2001-2016 Ravenbrook Limited
|
||||
* <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
|
|
|
|||
|
|
@ -574,9 +574,8 @@ static void StackScan(mps_arena_t arena, int on)
|
|||
{
|
||||
if(on) {
|
||||
Insist(root_stackreg == NULL);
|
||||
die(mps_root_create_reg(&root_stackreg, arena,
|
||||
mps_rank_ambig(), (mps_rm_t)0, stack_thr,
|
||||
mps_stack_scan_ambig, stack_start, 0),
|
||||
die(mps_root_create_thread(&root_stackreg, arena,
|
||||
stack_thr, stack_start),
|
||||
"root_stackreg");
|
||||
Insist(root_stackreg != NULL);
|
||||
} else {
|
||||
|
|
@ -762,9 +761,8 @@ static void *testscriptB(void *arg, size_t s)
|
|||
/* root_stackreg: stack & registers are ambiguous roots = mutator's workspace */
|
||||
stack_start = &stack_starts_here;
|
||||
stack_thr = thr;
|
||||
die(mps_root_create_reg(&root_stackreg, arena,
|
||||
mps_rank_ambig(), (mps_rm_t)0, stack_thr,
|
||||
mps_stack_scan_ambig, stack_start, 0),
|
||||
die(mps_root_create_thread(&root_stackreg, arena,
|
||||
stack_thr, stack_start),
|
||||
"root_stackreg");
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -330,9 +330,8 @@ static void *testscriptB(void *arg, size_t s)
|
|||
die(mps_ap_create(&ap, amc, mps_rank_exact()), "ap_create");
|
||||
|
||||
/* root_stackreg: stack & registers are ambiguous roots = mutator's workspace */
|
||||
die(mps_root_create_reg(&root_stackreg, arena,
|
||||
mps_rank_ambig(), (mps_rm_t)0, thr,
|
||||
mps_stack_scan_ambig, &stack_starts_here, 0),
|
||||
die(mps_root_create_thread(&root_stackreg, arena,
|
||||
thr, &stack_starts_here),
|
||||
"root_stackreg");
|
||||
|
||||
/* Make myrootCOUNT registered-for-finalization objects. */
|
||||
|
|
|
|||
40
mps/configure
vendored
40
mps/configure
vendored
|
|
@ -1,6 +1,6 @@
|
|||
#! /bin/sh
|
||||
# Guess values for system-dependent variables and create Makefiles.
|
||||
# Generated by GNU Autoconf 2.69 for Memory Pool System Kit release/1.114.0.
|
||||
# Generated by GNU Autoconf 2.69 for Memory Pool System Kit release/1.115.0.
|
||||
#
|
||||
# Report bugs to <mps-questions@ravenbrook.com>.
|
||||
#
|
||||
|
|
@ -580,8 +580,8 @@ MAKEFLAGS=
|
|||
# Identity of this package.
|
||||
PACKAGE_NAME='Memory Pool System Kit'
|
||||
PACKAGE_TARNAME='mps-kit'
|
||||
PACKAGE_VERSION='release/1.114.0'
|
||||
PACKAGE_STRING='Memory Pool System Kit release/1.114.0'
|
||||
PACKAGE_VERSION='release/1.115.0'
|
||||
PACKAGE_STRING='Memory Pool System Kit release/1.115.0'
|
||||
PACKAGE_BUGREPORT='mps-questions@ravenbrook.com'
|
||||
PACKAGE_URL='http://www.ravenbrook.com/project/mps/'
|
||||
|
||||
|
|
@ -1245,7 +1245,7 @@ if test "$ac_init_help" = "long"; then
|
|||
# Omit some internal or obsolete options to make the list less imposing.
|
||||
# This message is too long to be a string in the A/UX 3.1 sh.
|
||||
cat <<_ACEOF
|
||||
\`configure' configures Memory Pool System Kit release/1.114.0 to adapt to many kinds of systems.
|
||||
\`configure' configures Memory Pool System Kit release/1.115.0 to adapt to many kinds of systems.
|
||||
|
||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||
|
||||
|
|
@ -1310,7 +1310,7 @@ fi
|
|||
|
||||
if test -n "$ac_init_help"; then
|
||||
case $ac_init_help in
|
||||
short | recursive ) echo "Configuration of Memory Pool System Kit release/1.114.0:";;
|
||||
short | recursive ) echo "Configuration of Memory Pool System Kit release/1.115.0:";;
|
||||
esac
|
||||
cat <<\_ACEOF
|
||||
|
||||
|
|
@ -1391,7 +1391,7 @@ fi
|
|||
test -n "$ac_init_help" && exit $ac_status
|
||||
if $ac_init_version; then
|
||||
cat <<\_ACEOF
|
||||
Memory Pool System Kit configure release/1.114.0
|
||||
Memory Pool System Kit configure release/1.115.0
|
||||
generated by GNU Autoconf 2.69
|
||||
|
||||
Copyright (C) 2012 Free Software Foundation, Inc.
|
||||
|
|
@ -1693,7 +1693,7 @@ cat >config.log <<_ACEOF
|
|||
This file contains any messages produced by compilers while
|
||||
running configure, to aid debugging if configure makes a mistake.
|
||||
|
||||
It was created by Memory Pool System Kit $as_me release/1.114.0, which was
|
||||
It was created by Memory Pool System Kit $as_me release/1.115.0, which was
|
||||
generated by GNU Autoconf 2.69. Invocation command line was
|
||||
|
||||
$ $0 $@
|
||||
|
|
@ -3524,6 +3524,28 @@ $as_echo "FreeBSD x86_64" >&6; }
|
|||
CPP="$CC -I/usr/local/include -E"
|
||||
PFMCFLAGS="$CFLAGS_GC"
|
||||
;;
|
||||
i*86-*-freebsd*/yes)
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: FreeBSD x86" >&5
|
||||
$as_echo "FreeBSD x86" >&6; }
|
||||
MPS_OS_NAME=fr
|
||||
MPS_ARCH_NAME=i3
|
||||
MPS_BUILD_NAME=ll
|
||||
# Need /usr/local/include in order to find sqlite3.h
|
||||
CFLAGS="-I/usr/local/include"
|
||||
CPP="$CC -I/usr/local/include -E"
|
||||
PFMCFLAGS="$CFLAGS_LL"
|
||||
;;
|
||||
amd64-*-freebsd*/no | x86_64-*-freebsd*/no)
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: FreeBSD x86_64" >&5
|
||||
$as_echo "FreeBSD x86_64" >&6; }
|
||||
MPS_OS_NAME=fr
|
||||
MPS_ARCH_NAME=i6
|
||||
MPS_BUILD_NAME=ll
|
||||
# Need /usr/local/include in order to find sqlite3.h
|
||||
CFLAGS="-I/usr/local/include"
|
||||
CPP="$CC -I/usr/local/include -E"
|
||||
PFMCFLAGS="$CFLAGS_LL"
|
||||
;;
|
||||
*)
|
||||
as_fn_error $? "MPS does not support this platform out of the box. See manual/build.txt" "$LINENO" 5
|
||||
esac
|
||||
|
|
@ -4144,7 +4166,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
|
|||
# report actual input values of CONFIG_FILES etc. instead of their
|
||||
# values after options handling.
|
||||
ac_log="
|
||||
This file was extended by Memory Pool System Kit $as_me release/1.114.0, which was
|
||||
This file was extended by Memory Pool System Kit $as_me release/1.115.0, which was
|
||||
generated by GNU Autoconf 2.69. Invocation command line was
|
||||
|
||||
CONFIG_FILES = $CONFIG_FILES
|
||||
|
|
@ -4198,7 +4220,7 @@ _ACEOF
|
|||
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
||||
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
|
||||
ac_cs_version="\\
|
||||
Memory Pool System Kit config.status release/1.114.0
|
||||
Memory Pool System Kit config.status release/1.115.0
|
||||
configured by $0, generated by GNU Autoconf 2.69,
|
||||
with options \\"\$ac_cs_config\\"
|
||||
|
||||
|
|
|
|||
|
|
@ -98,6 +98,15 @@ case $host/$CLANG in
|
|||
CPP="$CC -I/usr/local/include -E"
|
||||
PFMCFLAGS="$CFLAGS_GC"
|
||||
;;
|
||||
amd64-*-freebsd*/yes | x86_64-*-freebsd*/yes)
|
||||
AC_MSG_RESULT([FreeBSD x86_64])
|
||||
MPS_OS_NAME=fr
|
||||
MPS_ARCH_NAME=i6
|
||||
MPS_BUILD_NAME=ll
|
||||
# Need /usr/local/include in order to find sqlite3.h
|
||||
CFLAGS="-I/usr/local/include"
|
||||
CPP="$CC -I/usr/local/include -E"
|
||||
PFMCFLAGS="$CFLAGS_GC"
|
||||
amd64-*-freebsd*/no | x86_64-*-freebsd*/no)
|
||||
AC_MSG_RESULT([FreeBSD x86_64])
|
||||
MPS_OS_NAME=fr
|
||||
|
|
@ -108,6 +117,26 @@ case $host/$CLANG in
|
|||
CPP="$CC -I/usr/local/include -E"
|
||||
PFMCFLAGS="$CFLAGS_GC"
|
||||
;;
|
||||
i*86-*-freebsd*/yes)
|
||||
AC_MSG_RESULT([FreeBSD x86])
|
||||
MPS_OS_NAME=fr
|
||||
MPS_ARCH_NAME=i3
|
||||
MPS_BUILD_NAME=ll
|
||||
# Need /usr/local/include in order to find sqlite3.h
|
||||
CFLAGS="-I/usr/local/include"
|
||||
CPP="$CC -I/usr/local/include -E"
|
||||
PFMCFLAGS="$CFLAGS_LL"
|
||||
;;
|
||||
amd64-*-freebsd*/no | x86_64-*-freebsd*/no)
|
||||
AC_MSG_RESULT([FreeBSD x86_64])
|
||||
MPS_OS_NAME=fr
|
||||
MPS_ARCH_NAME=i6
|
||||
MPS_BUILD_NAME=ll
|
||||
# Need /usr/local/include in order to find sqlite3.h
|
||||
CFLAGS="-I/usr/local/include"
|
||||
CPP="$CC -I/usr/local/include -E"
|
||||
PFMCFLAGS="$CFLAGS_LL"
|
||||
;;
|
||||
*)
|
||||
AC_MSG_ERROR([MPS does not support this platform out of the box. See manual/build.txt])
|
||||
esac
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ Fixed-length queues
|
|||
:Status: complete design
|
||||
:Revision: $Id$
|
||||
:Copyright: See section `Copyright and License`_.
|
||||
:Index terms: pair: fixed-length queues; design
|
||||
|
||||
|
||||
Introduction
|
||||
|
|
@ -119,7 +120,7 @@ Document History
|
|||
Copyright and License
|
||||
---------------------
|
||||
|
||||
Copyright © 2013-2014 Ravenbrook Limited. All rights reserved.
|
||||
Copyright © 2013-2016 Ravenbrook Limited. All rights reserved.
|
||||
<http://www.ravenbrook.com/>. This is an open source license. Contact
|
||||
Ravenbrook for commercial licensing options.
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ Bootstrapping
|
|||
:Status: incomplete design
|
||||
:Revision: $Id$
|
||||
:Copyright: See section `Copyright and License`_.
|
||||
:Index terms: pair: bootsrap; design
|
||||
:Index terms: pair: bootstrap; design
|
||||
|
||||
|
||||
Introduction
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ Coalescing block structures
|
|||
:Status: complete design
|
||||
:Revision: $Id$
|
||||
:Copyright: See section `Copyright and License`_.
|
||||
:Index terms: pair: coalescing block structures; design
|
||||
|
||||
|
||||
Introduction
|
||||
|
|
@ -281,7 +282,7 @@ Document History
|
|||
Copyright and License
|
||||
---------------------
|
||||
|
||||
Copyright © 1998-2014 Ravenbrook Limited. All rights reserved.
|
||||
Copyright © 1998-2016 Ravenbrook Limited. All rights reserved.
|
||||
<http://www.ravenbrook.com/>. This is an open source license. Contact
|
||||
Ravenbrook for commercial licensing options.
|
||||
|
||||
|
|
|
|||
133
mps/design/clock.txt
Normal file
133
mps/design/clock.txt
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
.. mode: -*- rst -*-
|
||||
|
||||
Fast high-resolution clock
|
||||
==========================
|
||||
|
||||
:Tag: design.mps.clock
|
||||
:Author: Gareth Rees
|
||||
:Date: 2016-03-06
|
||||
:Status: complete design
|
||||
:Revision: $Id: //info.ravenbrook.com/project/mps/master/design/abq.txt#5 $
|
||||
:Copyright: See section `Copyright and License`_.
|
||||
:Index terms: pair: clock; design
|
||||
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
_`.intro`: This is the design of the clock module, which implements a
|
||||
fast high-resolution clock for use by the telemetry system.
|
||||
|
||||
_`.readership`: This document is intended for any MPS developer.
|
||||
|
||||
|
||||
Requirements
|
||||
------------
|
||||
|
||||
_`.req.monotonic`: Successive calls to ``EVENT_CLOCK()`` must yield
|
||||
values that are monotonically increasing. (So that comparing the
|
||||
timestamp on two events never gives false positives.)
|
||||
|
||||
_`.req.fast`: ``EVENT_CLOCK()`` should take very little time; it
|
||||
should not require a system call. (So that programs that use the MPS
|
||||
remain usable when telemetry is turned on.)
|
||||
|
||||
_`.req.high-resolution`: Successive calls to ``EVENT_CLOCK()`` should
|
||||
yield values that are strictly monotonically increasing (so that
|
||||
sorting the telemetry stream puts the events in the order they
|
||||
happened).
|
||||
|
||||
|
||||
Interface
|
||||
---------
|
||||
|
||||
``EventClock``
|
||||
|
||||
_`.if.type`: The type of timestamps. It must be an unsigned 64-bit
|
||||
integral type, for example a ``typedef`` for ``uint64_t`` or
|
||||
``unsigned __int64``.
|
||||
|
||||
``EVENT_CLOCK_MAKE(lvalue, low, high)``
|
||||
|
||||
_`.if.make`: Construct an ``EventClock`` timestamp from its two
|
||||
halves. The first parameter is an lvalue with type ``EventClock``, and
|
||||
the second and third parameters are 32-bit unsigned integers. The
|
||||
macro must assign a timestamp to ``lvalue`` with the value ``(high
|
||||
<< 32) + low``.
|
||||
|
||||
``EVENT_CLOCK(lvalue)``
|
||||
|
||||
_`.if.get`: Assign an ``EventClock`` timestamp for the current time to
|
||||
``lvalue``, which is an lvalue with type ``EventClock``.
|
||||
|
||||
``EVENT_CLOCK_PRINT(FILE *stream, EventClock clock)``
|
||||
|
||||
_`.if.print`: Write the value of ``clock`` to the standard C output
|
||||
file handle ``stream`` as 16 hexadecimal digits (with leading zeros,
|
||||
and capital letters A to F).
|
||||
|
||||
``EVENT_CLOCK_WRITE(mps_lib_FILE *stream, EventClock clock)``
|
||||
|
||||
_`.if.write`: Write the value of ``clock`` to the output stream
|
||||
``stream`` as 16 hexadecimal digits (with leading zeros, and capital
|
||||
letters A to F). The macro should be implemented using ``WriteF()``.
|
||||
|
||||
|
||||
Implementation
|
||||
--------------
|
||||
|
||||
_`.impl.tsc`: On IA-32 and x86-64, the `Time Stamp Counter
|
||||
<https://en.wikipedia.org/wiki/Time_Stamp_Counter>`_ returned by the
|
||||
RDTSC instruction is a suitable clock for single-core CPUs, but on
|
||||
multiple-core CPUs, different cores may have different values or tick at different speeds, and so it may fail to meet `.req.monotonic`_.
|
||||
|
||||
|
||||
Document History
|
||||
----------------
|
||||
|
||||
- 2016-03-06 GDR_ Created.
|
||||
|
||||
.. _GDR: http://www.ravenbrook.com/consultants/gdr/
|
||||
|
||||
|
||||
Copyright and License
|
||||
---------------------
|
||||
|
||||
Copyright © 2016 Ravenbrook Limited. All rights reserved.
|
||||
<http://www.ravenbrook.com/>. This is an open source license. Contact
|
||||
Ravenbrook for commercial licensing options.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
#. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
#. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
#. Redistributions in any form must be accompanied by information on how
|
||||
to obtain complete source code for this software and any
|
||||
accompanying software that uses this software. The source code must
|
||||
either be included in the distribution or be available for no more than
|
||||
the cost of distribution plus a nominal fee, and must be freely
|
||||
redistributable under reasonable conditions. For an executable file,
|
||||
complete source code means the source code for all modules it contains.
|
||||
It does not include source code for modules or files that typically
|
||||
accompany the major components of the operating system on which the
|
||||
executable file runs.
|
||||
|
||||
**This software is provided by the copyright holders and contributors
|
||||
"as is" and any express or implied warranties, including, but not
|
||||
limited to, the implied warranties of merchantability, fitness for a
|
||||
particular purpose, or non-infringement, are disclaimed. In no event
|
||||
shall the copyright holders and contributors be liable for any direct,
|
||||
indirect, incidental, special, exemplary, or consequential damages
|
||||
(including, but not limited to, procurement of substitute goods or
|
||||
services; loss of use, data, or profits; or business interruption)
|
||||
however caused and on any theory of liability, whether in contract,
|
||||
strict liability, or tort (including negligence or otherwise) arising in
|
||||
any way out of the use of this software, even if advised of the
|
||||
possibility of such damage.**
|
||||
|
|
@ -75,7 +75,7 @@ _`.def.platform`: A *platform* is a combination of an architecture
|
|||
|
||||
_`.def.arch`: An *architecture* is processor type with associated calling
|
||||
conventions and other binary interface stuff these days often called the
|
||||
`ABI <http://en.wikipedia.org/wiki/Application_binary_interface>`_.
|
||||
`ABI <https://en.wikipedia.org/wiki/Application_binary_interface>`_.
|
||||
Most importantly for the MPS it determines the layout of the register
|
||||
file, thread context, and thread stack.
|
||||
|
||||
|
|
@ -610,7 +610,7 @@ Document History
|
|||
Copyright and License
|
||||
---------------------
|
||||
|
||||
Copyright © 2013-2014 Ravenbrook Limited. All rights reserved.
|
||||
Copyright © 2013-2016 Ravenbrook Limited. All rights reserved.
|
||||
<http://www.ravenbrook.com/>. This is an open source license. Contact
|
||||
Ravenbrook for commercial licensing options.
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ Fail-over allocator
|
|||
:Status: complete design
|
||||
:Revision: $Id$
|
||||
:Copyright: See section `Copyright and License`_.
|
||||
:Index terms: pair: fail-over allocator; design
|
||||
|
||||
|
||||
Introduction
|
||||
|
|
@ -110,7 +111,7 @@ Document History
|
|||
Copyright and License
|
||||
---------------------
|
||||
|
||||
Copyright © 2014 Ravenbrook Limited. All rights reserved.
|
||||
Copyright © 2014-2016 Ravenbrook Limited. All rights reserved.
|
||||
<http://www.ravenbrook.com/>. This is an open source license. Contact
|
||||
Ravenbrook for commercial licensing options.
|
||||
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ buffer_ Allocation buffers and allocation points
|
|||
cbs_ Coalescing block structures
|
||||
check_ Checking
|
||||
class-interface_ Pool class interface
|
||||
clock_ Fast high-resolution clock
|
||||
collection_ Collection framework
|
||||
config_ MPS configuration
|
||||
critical-path_ The critical path through the MPS
|
||||
|
|
@ -128,6 +129,7 @@ writef_ The WriteF function
|
|||
.. _buffer: buffer
|
||||
.. _cbs: cbs
|
||||
.. _check: check
|
||||
.. _clock: clock
|
||||
.. _class-interface: class-interface
|
||||
.. _collection: collection
|
||||
.. _config: config
|
||||
|
|
@ -237,7 +239,7 @@ Document History
|
|||
Copyright and License
|
||||
---------------------
|
||||
|
||||
Copyright © 2002-2015 Ravenbrook Limited. All rights reserved.
|
||||
Copyright © 2002-2016 Ravenbrook Limited. All rights reserved.
|
||||
<http://www.ravenbrook.com/>. This is an open source license. Contact
|
||||
Ravenbrook for commercial licensing options.
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ Lands
|
|||
:Status: complete design
|
||||
:Revision: $Id$
|
||||
:Copyright: See section `Copyright and License`_.
|
||||
:Index terms: pair: lands; design
|
||||
|
||||
|
||||
Introduction
|
||||
|
|
@ -321,7 +322,7 @@ Document History
|
|||
Copyright and License
|
||||
---------------------
|
||||
|
||||
Copyright © 2014-2015 Ravenbrook Limited. All rights reserved.
|
||||
Copyright © 2014-2016 Ravenbrook Limited. All rights reserved.
|
||||
<http://www.ravenbrook.com/>. This is an open source license. Contact
|
||||
Ravenbrook for commercial licensing options.
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,9 @@ MV pool class
|
|||
:Status: incomplete design
|
||||
:Revision: $Id$
|
||||
:Copyright: See `Copyright and License`_.
|
||||
:Index terms:
|
||||
pair: MV pool class; design
|
||||
single: pool class; MV design
|
||||
|
||||
|
||||
Implementation
|
||||
|
|
@ -44,7 +47,7 @@ Document History
|
|||
Copyright and License
|
||||
---------------------
|
||||
|
||||
Copyright © 2013-2014 Ravenbrook Limited. All rights reserved.
|
||||
Copyright © 2013-2016 Ravenbrook Limited. All rights reserved.
|
||||
<http://www.ravenbrook.com/>. This is an open source license. Contact
|
||||
Ravenbrook for commercial licensing options.
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,9 @@ Manual Variable Temporal (MVT) pool design
|
|||
:Status: incomplete design
|
||||
:Revision: $Id$
|
||||
:Copyright: See section `C. Copyright and License`_.
|
||||
:Index terms:
|
||||
pair: MVT pool class; design
|
||||
single: pool class; MVT design
|
||||
|
||||
|
||||
Introduction
|
||||
|
|
@ -1021,7 +1024,7 @@ B. Document History
|
|||
C. Copyright and License
|
||||
------------------------
|
||||
|
||||
Copyright (C) 2002-2014 Ravenbrook Limited. All rights reserved.
|
||||
Copyright (C) 2002-2016 Ravenbrook Limited. All rights reserved.
|
||||
<http://www.ravenbrook.com/>. This is an open source license. Contact
|
||||
Ravenbrook for commercial licensing options.
|
||||
|
||||
|
|
|
|||
|
|
@ -104,11 +104,11 @@ instruction which was caused the fault to be re-executed. Return
|
|||
This function is only called if ``ProtCanStepInstruction(context)``
|
||||
returned ``TRUE``.
|
||||
|
||||
``Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext context)``
|
||||
``Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext context, mps_area_scan_t scan, void *closure)``
|
||||
|
||||
_`.if.context.scan`: Scan all roots found in ``context`` using the
|
||||
given scan state (typically by calling ``TraceScanAreaTagged()``), and
|
||||
return the result code from the scanner.
|
||||
given scan state by calling ``scan``, and return the result code from
|
||||
the scanner.
|
||||
|
||||
``Addr MutatorFaultContextSP(MutatorFaultContext context)``
|
||||
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ checking and dynamic scope checking. They are a simplified form of
|
|||
"Structure Marking", a technique used in the Multics filesystem
|
||||
[THVV_1995]_.
|
||||
|
||||
.. _`magic numbers`: http://en.wikipedia.org/wiki/Magic_number_(programming)
|
||||
.. _`magic numbers`: https://en.wikipedia.org/wiki/Magic_number_(programming)
|
||||
|
||||
|
||||
Definitions
|
||||
|
|
@ -177,7 +177,7 @@ Document History
|
|||
Copyright and License
|
||||
---------------------
|
||||
|
||||
Copyright © 2013-2014 Ravenbrook Limited. All rights reserved.
|
||||
Copyright © 2013-2016 Ravenbrook Limited. All rights reserved.
|
||||
<http://www.ravenbrook.com/>. This is an open source license. Contact
|
||||
Ravenbrook for commercial licensing options.
|
||||
|
||||
|
|
|
|||
|
|
@ -66,21 +66,23 @@ been spilled onto the stack by the time the MPS is entered, so will be
|
|||
scanned by the stack scan. Floating-point registers and debugging
|
||||
registers do not, as far as we are aware, contain pointers.
|
||||
|
||||
_`.sol.inner`: Having located the top of the stack (``stackTop``), and
|
||||
spilled the root registers into the next ``n`` words, implementations
|
||||
call the generic function ``StackScanInner(ss, stackBot, stackTop,
|
||||
n)`` to actually do the scanning.
|
||||
_`.sol.inner`: Having located the hot end of the stack (``stackHot``),
|
||||
and spilled the root registers into the next ``n`` words,
|
||||
implementations call the generic higher-order function
|
||||
``StackScanInner(ss, stackCold, stackHot, n, scan_area, closure)`` to actually do the scanning.
|
||||
|
||||
|
||||
Interface
|
||||
---------
|
||||
|
||||
``Res StackScan(ScanState ss, Addr *stackBot)``
|
||||
``Res StackScan(ScanState ss, Word *stackCold,
|
||||
mps_area_scan_t scan_area,
|
||||
void *closure)``
|
||||
|
||||
_`.if.scan`: Scan the root registers of the current thread, and the
|
||||
control stack between ``stackBot`` and the top of the stack, in the
|
||||
context of the given scan state. Return ``ResOK`` if successful, or
|
||||
another result code if not.
|
||||
control stack between ``stackCold`` and the hot end of the stack, in
|
||||
the context of the given scan state, using ``scan_area``. Return
|
||||
``ResOK`` if successful, or another result code if not.
|
||||
|
||||
|
||||
Issue
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ MPS Strategy
|
|||
:Date: 2013-06-04
|
||||
:Revision: $Id$
|
||||
:Copyright: See section `Copyright and License`_.
|
||||
:Index terms: pair: strategy; design
|
||||
|
||||
|
||||
Introduction
|
||||
|
|
@ -555,7 +556,7 @@ Document History
|
|||
Copyright and License
|
||||
---------------------
|
||||
|
||||
Copyright © 2013-2014 Ravenbrook Limited. All rights reserved.
|
||||
Copyright © 2013-2016 Ravenbrook Limited. All rights reserved.
|
||||
<http://www.ravenbrook.com/>. This is an open source license. Contact
|
||||
Ravenbrook for commercial licensing options.
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ Tests
|
|||
:Status: incomplete design
|
||||
:Revision: $Id$
|
||||
:Copyright: See `Copyright and License`_.
|
||||
:Index terms: pair: tests; design
|
||||
|
||||
|
||||
Introduction
|
||||
|
|
@ -75,7 +76,7 @@ Document History
|
|||
Copyright and License
|
||||
---------------------
|
||||
|
||||
Copyright © 2013-2014 Ravenbrook Limited. All rights reserved.
|
||||
Copyright © 2013-2016 Ravenbrook Limited. All rights reserved.
|
||||
<http://www.ravenbrook.com/>. This is an open source license. Contact
|
||||
Ravenbrook for commercial licensing options.
|
||||
|
||||
|
|
|
|||
|
|
@ -153,15 +153,15 @@ threads are discovered to have terminated, move them to ``deadRing``.
|
|||
_`.if.ring.thread`: Return the thread that owns the given element of
|
||||
the thread ring.
|
||||
|
||||
``Res ThreadScan(ScanState ss, Thread thread, void *stackBot)``
|
||||
``Res ThreadScan(ScanState ss, Thread thread, Word *stackCold, mps_area_scan_t scan_area, void *closure)``
|
||||
|
||||
_`.if.scan`: Scan the stacks and root registers of ``thread``,
|
||||
treating each value found as an ambiguous reference. ``stackBot``
|
||||
points to the "bottom" of the thread's stack---this is the value that
|
||||
was supplied by the client program when it called
|
||||
``mps_root_create_reg()``. In the common case, where the stack grows
|
||||
downwards, ``stackBot`` is actually the highest stack address. Return
|
||||
``ResOK`` if successful, another result code otherwise.
|
||||
_`.if.scan`: Scan the stacks and root registers of ``thread``, using
|
||||
``ss`` and ``scan_area``. ``stackCold`` points to the cold end of the
|
||||
thread's stack---this is the value that was supplied by the client
|
||||
program when it called ``mps_root_create_thread()``. In the common
|
||||
case, where the stack grows downwards, ``stackCold`` is the highest
|
||||
stack address. Return ``ResOK`` if successful, another result code
|
||||
otherwise.
|
||||
|
||||
|
||||
Implementations
|
||||
|
|
|
|||
|
|
@ -4311,7 +4311,6 @@ static int start(int argc, char *argv[])
|
|||
size_t i;
|
||||
volatile obj_t env, op_env, obj;
|
||||
jmp_buf jb;
|
||||
mps_addr_t ref;
|
||||
mps_res_t res;
|
||||
mps_root_t globals_root;
|
||||
int exit_code = EXIT_SUCCESS;
|
||||
|
|
@ -4325,13 +4324,14 @@ static int start(int argc, char *argv[])
|
|||
|
||||
/* We must register the global variable 'symtab' as a root before
|
||||
creating the symbol table, otherwise the symbol table might be
|
||||
collected in the interval between creation and registration. But
|
||||
we must also ensure that 'symtab' is valid before registration
|
||||
(in this case, by setting it to NULL). See topic/root. */
|
||||
collected in the interval between creation and
|
||||
registration. But we must also ensure that 'symtab' is valid
|
||||
before registration (in this case, by setting it to NULL). See
|
||||
topic/root. */
|
||||
symtab = NULL;
|
||||
ref = &symtab;
|
||||
res = mps_root_create_table(&symtab_root, arena, mps_rank_exact(), 0,
|
||||
ref, 1);
|
||||
res = mps_root_create_area(&symtab_root, arena, mps_rank_exact(), 0,
|
||||
&symtab, &symtab + 1,
|
||||
mps_scan_area, NULL);
|
||||
if(res != MPS_RES_OK) error("Couldn't register symtab root");
|
||||
|
||||
/* The symbol table is strong-key weak-value. */
|
||||
|
|
@ -4582,14 +4582,7 @@ int main(int argc, char *argv[])
|
|||
need to be scanned by the MPS because we are passing references to
|
||||
objects around in C parameters, return values, and keeping them in
|
||||
automatic local variables. See topic/root. */
|
||||
res = mps_root_create_reg(®_root,
|
||||
arena,
|
||||
mps_rank_ambig(),
|
||||
0,
|
||||
thread,
|
||||
mps_stack_scan_ambig,
|
||||
marker,
|
||||
0);
|
||||
res = mps_root_create_thread(®_root, arena, thread, marker);
|
||||
if (res != MPS_RES_OK) error("Couldn't create root");
|
||||
|
||||
/* Make sure we can pick up finalization messages. */
|
||||
|
|
|
|||
|
|
@ -759,7 +759,6 @@ static void rehash(void) {
|
|||
size_t old_symtab_size = symtab_size;
|
||||
mps_root_t old_symtab_root = symtab_root;
|
||||
unsigned i;
|
||||
mps_addr_t ref;
|
||||
mps_res_t res;
|
||||
|
||||
symtab_size *= 2;
|
||||
|
|
@ -770,14 +769,15 @@ static void rehash(void) {
|
|||
for(i = 0; i < symtab_size; ++i)
|
||||
symtab[i] = NULL;
|
||||
|
||||
/* Once the symbol table is initialized with scannable references (NULL
|
||||
in this case) we must register it as a root before we copy objects
|
||||
across from the old symbol table. The MPS might be moving objects
|
||||
in memory at any time, and will arrange that both copies are updated
|
||||
atomically to the mutator (this interpreter). */
|
||||
ref = symtab;
|
||||
res = mps_root_create_table(&symtab_root, arena, mps_rank_exact(), 0,
|
||||
ref, symtab_size);
|
||||
/* %%MPS: Once the symbol table is initialized with scannable
|
||||
references (NULL in this case) we must register it as a root
|
||||
before we copy objects across from the old symbol table. The MPS
|
||||
might be moving objects in memory at any time, and will arrange
|
||||
that both copies are updated atomically to the mutator (this
|
||||
interpreter). */
|
||||
res = mps_root_create_area(&symtab_root, arena, mps_rank_exact(), 0,
|
||||
symtab, symtab + symtab_size,
|
||||
mps_scan_area, NULL);
|
||||
if(res != MPS_RES_OK) error("Couldn't register new symtab root");
|
||||
|
||||
for(i = 0; i < old_symtab_size; ++i)
|
||||
|
|
@ -4243,7 +4243,6 @@ static int start(int argc, char *argv[])
|
|||
size_t i;
|
||||
volatile obj_t env, op_env, obj;
|
||||
jmp_buf jb;
|
||||
mps_addr_t ref;
|
||||
mps_res_t res;
|
||||
mps_root_t globals_root;
|
||||
int exit_code = EXIT_SUCCESS;
|
||||
|
|
@ -4261,9 +4260,9 @@ static int start(int argc, char *argv[])
|
|||
pointers -- NULL in this case. Random values look like false
|
||||
references into MPS memory and cause undefined behaviour (most likely
|
||||
assertion failures). See topic/root. */
|
||||
ref = symtab;
|
||||
res = mps_root_create_table(&symtab_root, arena, mps_rank_exact(), 0,
|
||||
ref, symtab_size);
|
||||
res = mps_root_create_area(&symtab_root, arena, mps_rank_exact(), 0,
|
||||
symtab, symtab + symtab_size,
|
||||
mps_scan_area, NULL);
|
||||
if(res != MPS_RES_OK) error("Couldn't register symtab root");
|
||||
|
||||
error_handler = &jb;
|
||||
|
|
@ -4477,14 +4476,7 @@ int main(int argc, char *argv[])
|
|||
need to be scanned by the MPS because we are passing references to
|
||||
objects around in C parameters, return values, and keeping them in
|
||||
automatic local variables. See topic/root. */
|
||||
res = mps_root_create_reg(®_root,
|
||||
arena,
|
||||
mps_rank_ambig(),
|
||||
0,
|
||||
thread,
|
||||
mps_stack_scan_ambig,
|
||||
marker,
|
||||
0);
|
||||
res = mps_root_create_thread(®_root, arena, thread, marker);
|
||||
if (res != MPS_RES_OK) error("Couldn't create root");
|
||||
|
||||
/* Make sure we can pick up finalization messages. */
|
||||
|
|
|
|||
449
mps/manual/source/code-index.rst
Normal file
449
mps/manual/source/code-index.rst
Normal file
|
|
@ -0,0 +1,449 @@
|
|||
.. _code-index:
|
||||
|
||||
Index to source code
|
||||
====================
|
||||
|
||||
|
||||
External MPS interface
|
||||
----------------------
|
||||
|
||||
The external MPS interface consists of header files that the
|
||||
:term:`client program` is expected to include, plus the single-file
|
||||
source code (mps.c). See design.mps.interface-c_.
|
||||
|
||||
=========== ==================================================================
|
||||
File Description
|
||||
=========== ==================================================================
|
||||
mps.h Public MPS interface.
|
||||
mps.c Single-file source code. See :ref:`guide-build`.
|
||||
mpsacl.h :ref:`topic-arena-client` external interface.
|
||||
mpsavm.h :ref:`topic-arena-vm` external interface.
|
||||
mpscamc.h :ref:`pool-amc` pool class external interface.
|
||||
mpscams.h :ref:`pool-ams` pool class external interface.
|
||||
mpscawl.h :ref:`pool-awl` pool class external interface.
|
||||
mpsclo.h :ref:`pool-lo` pool class external interface.
|
||||
mpscmfs.h :ref:`pool-mfs` pool class external interface.
|
||||
mpscmv.h :ref:`pool-mv` pool class external interface.
|
||||
mpscmv2.h Former (deprecated) :ref:`pool-mvt` pool class interface.
|
||||
mpscmvff.h :ref:`pool-mvff` pool class external interface.
|
||||
mpscmvt.h :ref:`pool-mvt` pool class external interface.
|
||||
mpscsnc.h :ref:`pool-snc` pool class external interface.
|
||||
mpsio.h :ref:`topic-plinth-io` interface.
|
||||
mpslib.h :ref:`topic-plinth-lib` interface.
|
||||
=========== ==================================================================
|
||||
|
||||
|
||||
Plinth
|
||||
------
|
||||
|
||||
The :term:`plinth` provides an interface between the MPS and the
|
||||
execution environment, to help support :term:`freestanding`
|
||||
implementations. See :ref:`topic-plinth`.
|
||||
|
||||
=========== ==================================================================
|
||||
File Description
|
||||
=========== ==================================================================
|
||||
mpsioan.c :ref:`topic-plinth-io` for "ANSI" (hosted) environments.
|
||||
mpsliban.c :ref:`topic-plinth-lib` for "ANSI" (hosted) environments.
|
||||
=========== ==================================================================
|
||||
|
||||
|
||||
Configuration
|
||||
-------------
|
||||
|
||||
These header files provide platform-specific constants, type
|
||||
declarations, and macros. See :ref:`topic-porting` and
|
||||
design.mps.config_.
|
||||
|
||||
=========== ==================================================================
|
||||
File Description
|
||||
=========== ==================================================================
|
||||
clock.h Fast high-resolution clocks.
|
||||
config.h MPS configuration header.
|
||||
mpstd.h Target detection header.
|
||||
=========== ==================================================================
|
||||
|
||||
|
||||
Core MPS
|
||||
--------
|
||||
|
||||
============ =================================================================
|
||||
File Description
|
||||
============ =================================================================
|
||||
abq.c Fixed-length queue implementation. See design.mps.abq_.
|
||||
abq.h Fixed-length queue interface. See design.mps.abq_.
|
||||
arena.c Arena implementation. See design.mps.arena_.
|
||||
arenacl.c :ref:`topic-arena-client` implementation.
|
||||
arenavm.c :ref:`topic-arena-vm` implementation.
|
||||
arg.c :ref:`topic-keyword` implementation.
|
||||
arg.h :ref:`topic-keyword` interface.
|
||||
boot.c Bootstrap allocator implementation. See design.mps.bootstrap_.
|
||||
boot.h Bootstrap allocator interface. See design.mps.bootstrap_.
|
||||
bt.c Bit table implementation. See design.mps.bt_.
|
||||
bt.h Bit table interface. See design.mps.bt_.
|
||||
buffer.c Buffer implementation. See design.mps.buffer_.
|
||||
cbs.c Coalescing block implementation. See design.mps.cbs_.
|
||||
cbs.h Coalescing block interface. See design.mps.cbs_.
|
||||
check.h Assertion interface. See design.mps.check_.
|
||||
dbgpool.c :ref:`topic-debugging` implementation.
|
||||
dbgpool.h :ref:`topic-debugging` interface.
|
||||
dbgpooli.c :ref:`topic-debugging` external interface.
|
||||
event.c :ref:`topic-telemetry` implementation.
|
||||
event.h :ref:`topic-telemetry` interface (internal).
|
||||
eventcom.h :ref:`topic-telemetry` interface (auxiliary programs).
|
||||
eventdef.h :ref:`topic-telemetry` event definitions.
|
||||
failover.c Fail-over allocator implementation. See design.mps.failover_.
|
||||
failover.h Fail-over allocator interface. See design.mps.failover_.
|
||||
format.c :ref:`topic-format` implementation.
|
||||
freelist.c Freelist allocator implementation. See design.mps.freelist_.
|
||||
freelist.h Freelist allocator interface. See design.mps.freelist_.
|
||||
global.c Global arena implementation.
|
||||
land.c Land implementation. See design.mps.land_.
|
||||
ld.c :ref:`topic-location` implementation.
|
||||
locus.c Locus manager implementation. See design.mps.locus_.
|
||||
locus.h Locus manager interface. See design.mps.locus_.
|
||||
message.c :ref:`topic-message` implementation.
|
||||
meter.c Debugging accumulator implementation.
|
||||
meter.h Debugging accumulator interface.
|
||||
misc.h Miscellaneous constant and macro definitions.
|
||||
mpm.c Miscellaneous support functions. See design.mps.writef_.
|
||||
mpm.h Core MPS interface. ("MPM" = "Memory Pool Manager")
|
||||
mpmst.h Core data structure declarations.
|
||||
mpmtypes.h Core type declarations.
|
||||
mpsi.c External interface implementation. See design.mps.interface-c_.
|
||||
mpsiw3.c Additional external interface implementation for Windows.
|
||||
mpswin.h Wrapper for windows.h.
|
||||
nailboard.c Nailboard implementation. See design.mps.nailboard_.
|
||||
nailboard.h Nailboard interface. See design.mps.nailboard_.
|
||||
policy.c Collection policy decisions. See design.mps.strategy_.
|
||||
pool.c Pool implementation. See design.mps.pool_.
|
||||
poolabs.c Abstract pool classes.
|
||||
poolmrg.c Manual Rank Guardian pool implementation. See design.mps.poolmrg_.
|
||||
poolmrg.h Manual Rank Guardian pool interface. See design.mps.poolmrg_.
|
||||
protocol.c Inheritance protocol implementation. See design.mps.protocol_.
|
||||
protocol.h Inheritance protocol interface. See design.mps.protocol_.
|
||||
range.c Address ranges implementation. See design.mps.range_.
|
||||
range.h Address ranges interface. See design.mps.range_.
|
||||
ref.c Ranks and zones implementation.
|
||||
reserv.c Reservoir pool implementation. See design.mps.reservoir_.
|
||||
ring.c Ring implementation. See design.mps.ring_.
|
||||
ring.h Ring interface. See design.mps.ring_.
|
||||
root.c :ref:`topic-root` implementation.
|
||||
sa.c Sparse array implementation.
|
||||
sa.h Sparse array interface.
|
||||
sac.c :ref:`topic-cache` implementation.
|
||||
sac.h :ref:`topic-cache` interface.
|
||||
sc.h Stack context interface.
|
||||
scan.c :ref:`topic-scanning` functions.
|
||||
seg.c Segment implementation. See design.mps.seg_.
|
||||
shield.c Shield implementation. See design.mps.shield_.
|
||||
splay.c Splay tree implementation. See design.mps.splay_.
|
||||
splay.h Splay tree interface. See design.mps.splay_.
|
||||
trace.c Trace implementation. See design.mps.trace_.
|
||||
traceanc.c More trace implementation. See design.mps.trace_.
|
||||
tract.c Chunk and tract implementation. See design.mps.arena_.
|
||||
tract.h Chunk and tract interface. See design.mps.arena_.
|
||||
tree.c Binary tree implementation.
|
||||
tree.h Binary tree interface.
|
||||
version.c MPS version implementation. See design.mps.version_.
|
||||
walk.c Formatted object walker.
|
||||
============ =================================================================
|
||||
|
||||
|
||||
Platform interfaces
|
||||
-------------------
|
||||
|
||||
These modules provide interfaces to features that are not available in
|
||||
standard C, and so may need to be ported to new platforms. See
|
||||
:ref:`topic-porting`.
|
||||
|
||||
============ =================================================================
|
||||
File Description
|
||||
============ =================================================================
|
||||
lock.h Lock interface. See design.mps.lock_.
|
||||
lockan.c Lock implementation for standard C.
|
||||
lockix.c Lock implementation for POSIX.
|
||||
lockli.c Lock implementation for Linux.
|
||||
lockw3.c Lock implementation for Windows.
|
||||
prmcan.c Mutator context implementation for standard C.
|
||||
prmci3.h Mutator context interface for IA-32.
|
||||
prmci3fr.c Mutator context implementation for FreeBSD, IA-32.
|
||||
prmci3li.c Mutator context implementation for Linux, IA-32.
|
||||
prmci3w3.c Mutator context implementation for Windows, IA-32.
|
||||
prmci3xc.c Mutator context implementation for OS X, IA-32.
|
||||
prmci6.h Mutator context interface for x86-64.
|
||||
prmci6fr.c Mutator context implementation for FreeBSD, x86-64.
|
||||
prmci6li.c Mutator context implementation for Linux, x86-64.
|
||||
prmci6w3.c Mutator context implementation for Windows, x86-64.
|
||||
prmci6xc.c Mutator context implementation for OS X, x86-64.
|
||||
prmcix.h Mutator context interface for POSIX.
|
||||
prmcw3.h Mutator context interface for Windows.
|
||||
prmcxc.h Mutator context interface for OS X.
|
||||
prot.h Protection interface. See design.mps.prot_.
|
||||
protan.c Protection implementation for standard C.
|
||||
proti3.c Protection implementation for IA-32.
|
||||
proti6.c Protection implementation for x86-64.
|
||||
protix.c Protection implementation for POSIX.
|
||||
protli.c Protection implementation for Linux.
|
||||
protsgix.c Protection implementation for POSIX (signals part).
|
||||
protw3.c Protection implementation for Windows.
|
||||
protxc.c Protection implementation for OS X.
|
||||
protxc.h Protection interface for OS X.
|
||||
pthrdext.c Protection implementation for POSIX (threads part).
|
||||
pthrdext.h Protection interface for POSIX (threads part).
|
||||
sp.h Stack probe interface. See design.mps.sp_.
|
||||
span.c Stack probe implementation for standard C.
|
||||
spw3i3.c Stack probe implementation for Windows, IA-32.
|
||||
spw3i6.c Stack probe implementation for Windows, x86-64.
|
||||
ss.c Stack scanning implementation (common part).
|
||||
ss.h Stack scanning interface. See design.mps.ss_.
|
||||
ssan.c Stack scanning implementation for standard C.
|
||||
ssixi3.c Stack scanning implementation for POSIX, IA-32.
|
||||
ssixi6.c Stack scanning implementation for POSIX, x86-64.
|
||||
ssw3i3mv.c Stack scanning implementation for Windows, IA-32, Visual C.
|
||||
ssw3i3pc.c Stack scanning implementation for Windows, x86-64, Pelles C.
|
||||
ssw3i6mv.c Stack scanning implementation for Windows, IA-32, Visual C.
|
||||
ssw3i6pc.c Stack scanning implementation for Windows, x86-64, Pelles C.
|
||||
th.h Threads interface. See design.mps.thread-manager_.
|
||||
than.c Threads implementation for standard C.
|
||||
thix.c Threads implementation for POSIX.
|
||||
thw3.c Threads implementation for Windows.
|
||||
thw3.h Threads interface for Windows.
|
||||
thw3i3.c Threads implementation for Windows, IA-32.
|
||||
thw3i6.c Threads implementation for Windows, x86-64.
|
||||
thxc.c Threads implementation for OS X.
|
||||
vm.c Virtual memory implementation (common part).
|
||||
vm.h Virtual memory interface. See design.mps.vm_.
|
||||
vman.c Virtual memory implementation for standard C.
|
||||
vmix.c Virtual memory implementation for POSIX.
|
||||
vmw3.c Virtual memory implementation for Windows.
|
||||
============ =================================================================
|
||||
|
||||
|
||||
Pool classes
|
||||
------------
|
||||
|
||||
These files implement the supported :term:`pool classes`. Some of
|
||||
these (MFS, MV) are used internally by the MPS; the others are
|
||||
available for :term:`client programs` only. See :ref:`pool`.
|
||||
|
||||
=========== ==================================================================
|
||||
File Description
|
||||
=========== ==================================================================
|
||||
poolamc.c :ref:`pool-amc` implementation.
|
||||
poolams.c :ref:`pool-ams` implementation.
|
||||
poolams.h :ref:`pool-ams` internal interface.
|
||||
poolawl.c :ref:`pool-awl` implementation.
|
||||
poollo.c :ref:`pool-lo` implementation.
|
||||
poolmfs.c :ref:`pool-mfs` implementation.
|
||||
poolmfs.h :ref:`pool-mfs` internal interface.
|
||||
poolmv.c :ref:`pool-mv` implementation.
|
||||
poolmv.h :ref:`pool-mv` internal interface.
|
||||
poolmv2.c :ref:`pool-amc` implementation.
|
||||
poolmv2.h :ref:`pool-mvt` internal interface.
|
||||
poolmvff.c :ref:`pool-mvff` implementation.
|
||||
poolsnc.c :ref:`pool-snc` implementation.
|
||||
=========== ==================================================================
|
||||
|
||||
|
||||
Auxiliary programs
|
||||
------------------
|
||||
|
||||
These files implement auxiliary programs. See
|
||||
:ref:`topic-telemetry-utilities`.
|
||||
|
||||
=========== ==================================================================
|
||||
File Description
|
||||
=========== ==================================================================
|
||||
eventcnv.c :ref:`telemetry-mpseventcnv`.
|
||||
eventrep.c Event replaying implementation (broken).
|
||||
eventrep.h Event replaying interface (broken).
|
||||
eventsql.c :ref:`telemetry-mpseventsql`.
|
||||
eventtxt.c :ref:`telemetry-mpseventtxt`.
|
||||
getopt.h Command-line option interface. Adapted from FreeBSD.
|
||||
getoptl.c Command-line option implementation. Adapted from FreeBSD.
|
||||
replay.c Event replaying program (broken).
|
||||
table.c Address-based hash table implementation.
|
||||
table.h Address-based hash table interface.
|
||||
=========== ==================================================================
|
||||
|
||||
|
||||
Benchmarks
|
||||
----------
|
||||
|
||||
=========== ==================================================================
|
||||
File Description
|
||||
=========== ==================================================================
|
||||
djbench.c Benchmark for manually managed pool classes.
|
||||
gcbench.c Benchmark for automatically managed pool classes.
|
||||
=========== ==================================================================
|
||||
|
||||
|
||||
Test support
|
||||
------------
|
||||
|
||||
This is code that's shared between test cases.
|
||||
|
||||
============ =================================================================
|
||||
File Description
|
||||
============ =================================================================
|
||||
fmtdy.c Dylan object format implementation.
|
||||
fmtdy.h Dylan object format interface.
|
||||
fmtdytst.c Dylan object constructor implementation.
|
||||
fmtdytst.h Dylan object constructor interface.
|
||||
fmthe.c Dylan-like object format with headers (implementation).
|
||||
fmthe.h Dylan-like object format with headers (interface).
|
||||
fmtno.c Null object format implementation.
|
||||
fmtno.h Null object format interface.
|
||||
fmtscheme.c Scheme object format implementation.
|
||||
fmtscheme.h Scheme object format interface.
|
||||
pooln.c Null pool implementation.
|
||||
pooln.h Null pool interface.
|
||||
testlib.c Test utilities implementation.
|
||||
testlib.h Test utilities interface.
|
||||
testthr.h Test threads interface. See design.mps.testthr_.
|
||||
testthrix.c Test threads implementation for POSIX.
|
||||
testthrw3.c Test threads implementation for Windows.
|
||||
============ =================================================================
|
||||
|
||||
|
||||
Interactive test cases
|
||||
----------------------
|
||||
|
||||
These test cases provide harness for interacting with parts of the
|
||||
MPS, for exploring the interface and testing by hand. These predate
|
||||
the use of continuous integration: we wouldn't write this kind of test
|
||||
case now.
|
||||
|
||||
=========== ==================================================================
|
||||
File Description
|
||||
=========== ==================================================================
|
||||
bttest.c Interactive bit tables test harness.
|
||||
teletest.c Interactive telemetry test harness.
|
||||
=========== ==================================================================
|
||||
|
||||
|
||||
Automated test cases
|
||||
--------------------
|
||||
|
||||
These are test cases that run automatically and form the main test
|
||||
suite. See design.mps.tests_.
|
||||
|
||||
================ =============================================================
|
||||
File Description
|
||||
================ =============================================================
|
||||
abqtest.c Fixed-length queue test.
|
||||
airtest.c Ambiguous interior reference test.
|
||||
amcss.c :ref:`pool-amc` stress test.
|
||||
amcsshe.c :ref:`pool-amc` stress test (using in-band headers).
|
||||
amcssth.c :ref:`pool-amc` stress test (using multiple threads).
|
||||
amsss.c :ref:`pool-ams` stress test.
|
||||
amssshe.c :ref:`pool-ams` stress test (using in-band headers).
|
||||
apss.c :ref:`topic-allocation-point` stress test.
|
||||
arenacv.c Arena coverage test.
|
||||
awlut.c :ref:`pool-awl` unit test.
|
||||
awluthe.c :ref:`pool-awl` unit test (using in-band headers).
|
||||
awlutth.c :ref:`pool-awl` unit test (using multiple threads).
|
||||
btcv.c Bit table coverage test.
|
||||
exposet0.c :c:func:`mps_arena_expose` test.
|
||||
expt825.c Regression test for job000825_.
|
||||
fbmtest.c Free block manager (CBS and Freelist) test.
|
||||
finalcv.c :ref:`topic-finalization` coverage test.
|
||||
finaltest.c :ref:`topic-finalization` test.
|
||||
fotest.c Failover allocator test.
|
||||
landtest.c Land test.
|
||||
locbwcss.c Locus backwards compatibility stress test.
|
||||
lockcov.c Lock coverage test.
|
||||
lockut.c Lock unit test.
|
||||
locusss.c Locus stress test.
|
||||
locv.c :ref:`pool-lo` coverage test.
|
||||
messtest.c :ref:`topic-message` test.
|
||||
mpmss.c Manual allocation stress test.
|
||||
mpsicv.c External interface coverage test.
|
||||
mv2test.c :ref:`pool-mvt` test.
|
||||
nailboardtest.c Nailboard test.
|
||||
poolncv.c Null pool class test.
|
||||
qs.c Quicksort test.
|
||||
sacss.c :ref:`topic-cache` stress test.
|
||||
segsmss.c Segment splitting and merging stress test.
|
||||
steptest.c :c:func:`mps_arena_step` test.
|
||||
tagtest.c Tagged pointer scanning test.
|
||||
walkt0.c Formatted object walking test.
|
||||
zcoll.c Garbage collection progress test.
|
||||
zmess.c Garbage collection and finalization message test.
|
||||
================ =============================================================
|
||||
|
||||
|
||||
Build infrastructure
|
||||
--------------------
|
||||
|
||||
These are makefiles (and makefile fragments) used to build the MPS.
|
||||
See :ref:`topic-porting`.
|
||||
|
||||
============= ================================================================
|
||||
File Description
|
||||
============= ================================================================
|
||||
anangc.gmk GNU makefile for platform ANANGC.
|
||||
ananll.gmk GNU makefile for platform ANANLL.
|
||||
ananmv.nmk NMAKE file for platform ANANMV.
|
||||
comm.gmk Common GNU make fragment.
|
||||
commpost.nmk Common NMAKE fragment (included before the compiler fragment).
|
||||
commpre.nmk Common NMAKE fragment (included after the compiler fragment).
|
||||
fri3gc.gmk GNU makefile for platform FRI3GC.
|
||||
fri3ll.gmk GNU makefile for platform FRI3LL.
|
||||
fri6gc.gmk GNU makefile for platform FRI6GC.
|
||||
fri6ll.gmk GNU makefile for platform FRI6LL.
|
||||
gc.gmk GNU make fragment for GCC.
|
||||
gp.gmk GNU make fragment for GCC/GProf (broken).
|
||||
lii3gc.gmk GNU makefile for platform LII3GC.
|
||||
lii6gc.gmk GNU makefile for platform LII6GC.
|
||||
lii6ll.gmk GNU makefile for platform LII6LL.
|
||||
ll.gmk GNU make fragment for Clang/LLVM.
|
||||
mv.nmk NMAKE fragment for Microsoft Visual C.
|
||||
pc.nmk NMAKE fragment for Pelles C.
|
||||
w3i3mv.nmk NMAKE file for platform W3I3MV.
|
||||
w3i3pc.nmk NMAKE file for platform W3I3PC.
|
||||
w3i6mv.nmk NMAKE file for platform W3I6MV.
|
||||
w3i6pc.nmk NMAKE file for platform W3I6PC.
|
||||
xci3gc.gmk GNU makefile for platform XCI3GC.
|
||||
xci6ll.gmk GNU makefile for platform XCI6LL.
|
||||
============= ================================================================
|
||||
|
||||
|
||||
.. _design.mps.abq: design/abq.html
|
||||
.. _design.mps.arena: design/arena.html
|
||||
.. _design.mps.bootstrap: design/bootstrap.html
|
||||
.. _design.mps.bt: design/bt.html
|
||||
.. _design.mps.buffer: design/buffer.html
|
||||
.. _design.mps.cbs: design/cbs.html
|
||||
.. _design.mps.check: design/check.html
|
||||
.. _design.mps.config: design/config.html
|
||||
.. _design.mps.failover: design/failover.html
|
||||
.. _design.mps.freelist: design/freelist.html
|
||||
.. _design.mps.interface-c: design/interface-c.html
|
||||
.. _design.mps.land: design/land.html
|
||||
.. _design.mps.lock: design/lock.html
|
||||
.. _design.mps.locus: design/locus.html
|
||||
.. _design.mps.nailboard: design/nailboard.html
|
||||
.. _design.mps.pool: design/pool.html
|
||||
.. _design.mps.poolmrg: design/poolmrg.html
|
||||
.. _design.mps.prmc: design/prmc.html
|
||||
.. _design.mps.protocol: design/protocol.html
|
||||
.. _design.mps.prot: design/prot.html
|
||||
.. _design.mps.range: design/range.html
|
||||
.. _design.mps.reservoir: design/reservoir.html
|
||||
.. _design.mps.ring: design/ring.html
|
||||
.. _design.mps.seg: design/seg.html
|
||||
.. _design.mps.shield: design/shield.html
|
||||
.. _design.mps.sp: design/sp.html
|
||||
.. _design.mps.splay: design/splay.html
|
||||
.. _design.mps.ss: design/ss.html
|
||||
.. _design.mps.strategy: design/strategy.html
|
||||
.. _design.mps.tests: design/tests.html
|
||||
.. _design.mps.testthr: design/testthr.html
|
||||
.. _design.mps.thread-manager: design/thread-manager.html
|
||||
.. _design.mps.trace: design/trace.html
|
||||
.. _design.mps.version: design/version.html
|
||||
.. _design.mps.vm: design/vm.html
|
||||
.. _design.mps.writef: design/writef.html
|
||||
.. _job000825: https://www.ravenbrook.com/project/mps/issue/job000825
|
||||
|
|
@ -10,6 +10,7 @@ Design
|
|||
an
|
||||
bootstrap
|
||||
cbs
|
||||
clock
|
||||
config
|
||||
critical-path
|
||||
exec-env
|
||||
|
|
|
|||
|
|
@ -20,9 +20,9 @@ TYPES = '''
|
|||
|
||||
AccessSet Accumulation Addr Align AllocFrame AllocPattern AP Arg
|
||||
Arena Attr Bool BootBlock BT Buffer BufferMode Byte Chain Chunk
|
||||
Clock Compare Count Epoch FindDelete Format FrameState Fun GenDesc
|
||||
Globals Index Land LD Lock LocusPref LocusPrefKind Message
|
||||
MessageType MutatorFaultContext Page Pointer Pool PoolGen
|
||||
Clock Compare Count Epoch EventClock FindDelete Format FrameState
|
||||
Fun GenDesc Globals Index Land LD Lock LocusPref LocusPrefKind
|
||||
Message MessageType MutatorFaultContext Page Pointer Pool PoolGen
|
||||
PThreadext Range Rank RankSet ReadonlyAddr Ref RefSet Res
|
||||
Reservoir Ring Root RootMode RootVar ScanState Seg SegBuf Serial
|
||||
Shift Sig Size Space SplayNode SplayTree StackContext Thread Trace
|
||||
|
|
@ -121,6 +121,8 @@ def convert_file(name, source, dest):
|
|||
s = design_ref.sub(r'\1.html', s)
|
||||
s = design_frag_ref.sub(r'\1.html#design.mps.\2.\3', s)
|
||||
s = history.sub('', s)
|
||||
# Don't try to format all the quoted code blocks as C.
|
||||
s = '.. highlight:: none\n\n' + s
|
||||
try:
|
||||
os.makedirs(os.path.dirname(dest))
|
||||
except:
|
||||
|
|
|
|||
|
|
@ -131,7 +131,7 @@ Memory Management Glossary: C
|
|||
|
||||
A cactus stack is a :term:`stack` with branches. When
|
||||
diagrammed, its shape resembles that of a `saguaro cactus
|
||||
<http://en.wikipedia.org/wiki/Saguaro>`_.
|
||||
<https://en.wikipedia.org/wiki/Saguaro>`_.
|
||||
|
||||
In languages that support :term:`continuations`,
|
||||
:term:`activation records` can have :term:`indefinite extent`.
|
||||
|
|
@ -285,6 +285,25 @@ Memory Management Glossary: C
|
|||
fragmentation, and which coalescing strategies are effective
|
||||
under what circumstances.
|
||||
|
||||
cold end
|
||||
|
||||
.. opposite:: :term:`hot end`
|
||||
|
||||
A :term:`control stack` has two ends: the oldest items are at
|
||||
the *cold end* and the newest items are at the *hot end*.
|
||||
Sometimes the cold end is called the "bottom" of the stack,
|
||||
but that is misleading when the stack grows downwards, as it
|
||||
does on common computing platforms.
|
||||
|
||||
.. mps:specific::
|
||||
|
||||
In order for the MPS to be able to :term:`scan`
|
||||
:term:`references` on the stack, the :term:`client
|
||||
program` must pass the location of the cold end of the
|
||||
stack (or the part of the stack that might contain
|
||||
references to memory managed by the MPS) to
|
||||
:c:func:`mps_root_create_thread`.
|
||||
|
||||
collect
|
||||
|
||||
An :term:`object` is collected when it is :term:`reclaimed` by
|
||||
|
|
@ -570,7 +589,7 @@ Memory Management Glossary: C
|
|||
|
||||
.. similar:: :term:`stack`.
|
||||
|
||||
.. seealso:: :term:`data stack`.
|
||||
.. seealso:: :term:`cold end`, :term:`data stack`, :term:`hot end`.
|
||||
|
||||
cool
|
||||
|
||||
|
|
|
|||
|
|
@ -118,6 +118,16 @@ Memory Management Glossary: H
|
|||
Select it by defining :c:macro:`CONFIG_VAR_HOT`. Compare
|
||||
:term:`cool` and :term:`rash`.
|
||||
|
||||
hot end
|
||||
|
||||
.. opposite:: :term:`cold end`
|
||||
|
||||
A :term:`control stack` has two ends: the oldest items are at
|
||||
the *cold end* and the newest items are at the *hot end*.
|
||||
Sometimes the hot end is called the "top" of the stack, but
|
||||
that is misleading when the stack grows downwards, as it does
|
||||
on common computing platforms.
|
||||
|
||||
huge page
|
||||
|
||||
.. aka:: *large page*, *superpage*.
|
||||
|
|
|
|||
|
|
@ -123,6 +123,13 @@ Memory Management Glossary: T
|
|||
stream can be configured by setting the :term:`telemetry
|
||||
filter`. See :ref:`topic-telemetry`.
|
||||
|
||||
telemetry system
|
||||
|
||||
.. mps:specific::
|
||||
|
||||
The subsystem of the MPS that outputs the :term:`telemetry
|
||||
stream`. See :ref:`topic-telemetry`.
|
||||
|
||||
tenuring
|
||||
|
||||
.. see:: :term:`promotion`.
|
||||
|
|
@ -181,9 +188,9 @@ Memory Management Glossary: T
|
|||
Threads are represented by values of type
|
||||
:c:type:`mps_thr_t`, created by calling
|
||||
:c:func:`mps_thread_reg`. In order for the MPS to find
|
||||
references on the control of the thread, the thread must
|
||||
be also be registered as a root by calling
|
||||
:c:func:`mps_root_create_reg`. See :ref:`topic-thread`.
|
||||
references on the control stack of the thread, the thread
|
||||
must be also be registered as a :term:`root` by calling
|
||||
:c:func:`mps_root_create_thread`. See :ref:`topic-thread`.
|
||||
|
||||
threatened set
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
.. highlight:: none
|
||||
|
||||
.. index::
|
||||
single: building
|
||||
single: compiling
|
||||
|
|
|
|||
|
|
@ -971,29 +971,21 @@ You register a thread with an :term:`arena` by calling
|
|||
res = mps_thread_reg(&thread, arena);
|
||||
if (res != MPS_RES_OK) error("Couldn't register thread");
|
||||
|
||||
You register the thread's registers and control stack as a root by
|
||||
calling :c:func:`mps_root_create_reg` and passing
|
||||
:c:func:`mps_stack_scan_ambig`::
|
||||
You register the thread's :term:`registers` and :term:`control stack`
|
||||
as a root by calling :c:func:`mps_root_create_thread`::
|
||||
|
||||
void *marker = ▮
|
||||
mps_root_t reg_root;
|
||||
res = mps_root_create_reg(®_root,
|
||||
arena,
|
||||
mps_rank_ambig(),
|
||||
0,
|
||||
thread,
|
||||
mps_stack_scan_ambig,
|
||||
marker,
|
||||
0);
|
||||
mps_root_t stack_root;
|
||||
res = mps_root_create_thread(®_root, arena, thread, marker);
|
||||
if (res != MPS_RES_OK) error("Couldn't create root");
|
||||
|
||||
In order to scan the control stack, the MPS needs to know where the
|
||||
bottom of the stack is, and that's the role of the ``marker``
|
||||
variable: the compiler places it on the stack, so its address is a
|
||||
position within the stack. As long as you don't exit from this
|
||||
function while the MPS is running, your program's active local
|
||||
variables will always be higher up on the stack than ``marker``, and
|
||||
so will be scanned for references by the MPS.
|
||||
:term:`cold end` of the stack is, and that's the role of the
|
||||
``marker`` variable: the compiler places it on the stack, so its
|
||||
address is a position within the stack. As long as you don't exit from
|
||||
this function while the MPS is running, your program's active local
|
||||
variables will always be placed on the stack after ``marker``, and so
|
||||
will be scanned for references by the MPS.
|
||||
|
||||
.. topics::
|
||||
|
||||
|
|
|
|||
|
|
@ -64,8 +64,8 @@ solved:
|
|||
|
||||
This can solved by storing the new array in a :term:`root` until
|
||||
the header has been updated. If the thread's stack has been
|
||||
registered as a root by calling :c:func:`mps_root_create_reg` then
|
||||
any local variable will do.
|
||||
registered as a root by calling :c:func:`mps_root_create_thread`
|
||||
then any local variable will do.
|
||||
|
||||
2. References in the new array must not be scanned until they have been
|
||||
copied or cleared. (Otherwise they will be invalid.)
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ Appendices
|
|||
|
||||
bib
|
||||
glossary/index
|
||||
code-index
|
||||
copyright
|
||||
contact
|
||||
contributing
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ The Memory Management Reference is maintained by `Ravenbrook Limited`_.
|
|||
|
||||
Most of it was originally written by memory management experts in the
|
||||
Adaptive Memory Management Group at `Harlequin Limited
|
||||
<http://en.wikipedia.org/wiki/Harlequin_(software_company)>`_:
|
||||
<https://en.wikipedia.org/wiki/Harlequin_(software_company)>`_:
|
||||
|
||||
* Nick Barnes
|
||||
* Richard Brooksby
|
||||
|
|
|
|||
|
|
@ -233,7 +233,7 @@ Memory management in various languages
|
|||
|
||||
Dylan is a modern programming language invented by Apple
|
||||
around 1993 and developed by `Harlequin
|
||||
<http://en.wikipedia.org/wiki/Harlequin_(software_company)>`_
|
||||
<https://en.wikipedia.org/wiki/Harlequin_(software_company)>`_
|
||||
and other partners. The language is a distillation of the best
|
||||
ideas in dynamic and object-oriented programming. Its
|
||||
ancestors include :term:`Lisp`, :term:`Smalltalk`, and
|
||||
|
|
@ -583,7 +583,7 @@ Memory management in various languages
|
|||
|
||||
.. link::
|
||||
|
||||
`Harlequin RIP <http://en.wikipedia.org/wiki/Harlequin_RIP>`_.
|
||||
`Harlequin RIP <https://en.wikipedia.org/wiki/Harlequin_RIP>`_.
|
||||
|
||||
Prolog
|
||||
|
||||
|
|
|
|||
|
|
@ -23,6 +23,23 @@ New features
|
|||
:c:macro:`MPS_KEY_SPARE_COMMIT_LIMIT` sets the :term:`spare
|
||||
commit limit` for the arena.
|
||||
|
||||
#. New area scanning functions :c:func:`mps_scan_area`,
|
||||
:c:func:`mps_scan_area_masked`, :c:func:`mps_scan_area_tagged`,
|
||||
:c:func:`mps_scan_area_tagged_or_zero` for use when scanning,
|
||||
especially when scanning threads and :term:`tagged references`.
|
||||
|
||||
#. New thread root functions :c:func:`mps_root_create_thread`,
|
||||
:c:func:`mps_root_create_thread_tagged`, and
|
||||
:c:func:`mps_root_create_thread_scanned` allow flexible scanning of
|
||||
thread stacks and registers in any format, with convenient
|
||||
implementations provided for :term:`tagged references`.
|
||||
|
||||
#. New function :c:func:`mps_root_create_table_tagged` for tables of roots
|
||||
containing :term:`tagged references`.
|
||||
|
||||
#. New area root functions :c:func:`mps_root_create_area` and
|
||||
:c:func:`mps_root_create_area_tagged` for areas of memory
|
||||
that can be scanned by area scanning functions.
|
||||
|
||||
Interface changes
|
||||
.................
|
||||
|
|
@ -37,6 +54,12 @@ Interface changes
|
|||
deprecated in favour of the generic functions
|
||||
:c:func:`mps_pool_free_size` and :c:func:`mps_pool_total_size`.
|
||||
|
||||
#. The function :c:func:`mps_root_create_reg` is deprecated in favour
|
||||
of :c:func:`mps_root_create_thread_tagged`.
|
||||
|
||||
#. The function :c:func:`mps_root_create_table_masked` is deprecated in
|
||||
favour of :c:func:`mps_root_create_table_tagged`.
|
||||
|
||||
Other changes
|
||||
.............
|
||||
|
||||
|
|
|
|||
|
|
@ -79,6 +79,8 @@ Manual allocation
|
|||
.. index::
|
||||
single: allocation point
|
||||
|
||||
.. _topic-allocation-point:
|
||||
|
||||
Allocation points
|
||||
-----------------
|
||||
|
||||
|
|
@ -151,11 +153,11 @@ least) two steps, a *reserve* followed by a *commit*.
|
|||
|
||||
The description of the protocol assumes that you have declared
|
||||
your threads' :term:`control stacks` and :term:`registers` to be
|
||||
:term:`ambiguous roots`, by passing :c:func:`mps_stack_scan_ambig`
|
||||
to :c:func:`mps_root_create_reg`. This is the simplest way to
|
||||
write a client, but other scenarios are possible. Please
|
||||
:ref:`contact us <contact>` if your use case is not covered here
|
||||
(for example, if you need an exact collector).
|
||||
:term:`ambiguous roots`, by calling
|
||||
:c:func:`mps_root_create_thread`. This is the simplest way to write
|
||||
a client, but other scenarios are possible. Please :ref:`contact
|
||||
us <contact>` if your use case is not covered here (for example,
|
||||
if you need an exact collector).
|
||||
|
||||
When the client program is initializing a newly allocated object, you
|
||||
can think of it as being "in a race" with the MPS. Until the object is
|
||||
|
|
|
|||
|
|
@ -118,6 +118,240 @@ Deprecated in version 1.115
|
|||
is the sum of allocated space and free space.
|
||||
|
||||
|
||||
.. c:function:: mps_res_t mps_root_create_reg(mps_root_t *root_o, mps_arena_t arena, mps_rank_t rank, mps_rm_t rm, mps_thr_t thr, mps_reg_scan_t reg_scan, void *p, size_t s)
|
||||
|
||||
.. deprecated::
|
||||
|
||||
Use :c:func:`mps_root_create_thread` instead.
|
||||
|
||||
Register a :term:`root` that consists of the :term:`references`
|
||||
fixed in a :term:`thread's <thread>` registers and stack by a
|
||||
scanning function.
|
||||
|
||||
``root_o`` points to a location that will hold the address of the
|
||||
new root description.
|
||||
|
||||
``arena`` is the arena.
|
||||
|
||||
``rank`` is the :term:`rank` of references in the root.
|
||||
|
||||
``rm`` is the :term:`root mode`.
|
||||
|
||||
``thr`` is the thread.
|
||||
|
||||
``reg_scan`` is a scanning function. See :c:type:`mps_reg_scan_t`.
|
||||
|
||||
``p`` and ``s`` are arguments that will be passed to ``reg_scan`` each
|
||||
time it is called. This is intended to make it easy to pass, for
|
||||
example, an array and its size as parameters.
|
||||
|
||||
Returns :c:macro:`MPS_RES_OK` if the root was registered
|
||||
successfully, :c:macro:`MPS_RES_MEMORY` if the new root
|
||||
description could not be allocated, or another :term:`result code`
|
||||
if there was another error.
|
||||
|
||||
The registered root description persists until it is destroyed by
|
||||
calling :c:func:`mps_root_destroy`.
|
||||
|
||||
.. note::
|
||||
|
||||
It is not supported for :term:`client programs` to pass their
|
||||
own scanning functions to this function. The built-in MPS
|
||||
function :c:func:`mps_stack_scan_ambig` must be used. In this
|
||||
case the ``p`` argument must be a pointer to the :term:`cold
|
||||
end` of the thread's stack (or the part of the stack
|
||||
containing references to memory managed by the MPS). The ``s``
|
||||
argument is ignored.
|
||||
|
||||
.. c:function:: mps_res_t mps_root_create_table(mps_root_t *root_o, mps_arena_t arena, mps_rank_t rank, mps_rm_t rm, mps_addr_t *base, size_t count)
|
||||
|
||||
.. deprecated::
|
||||
|
||||
This function is equivalent to::
|
||||
|
||||
mps_root_create_area(root_o, arena, rank, mode,
|
||||
base, base + count,
|
||||
mps_scan_area, NULL, 0)
|
||||
|
||||
Register a :term:`root` that consists of a vector of
|
||||
:term:`references`.
|
||||
|
||||
``root_o`` points to a location that will hold the address of the
|
||||
new root description.
|
||||
|
||||
``arena`` is the arena.
|
||||
|
||||
``rank`` is the :term:`rank` of references in the root.
|
||||
|
||||
``rm`` is the :term:`root mode`.
|
||||
|
||||
``base`` points to a vector of references.
|
||||
|
||||
``count`` is the number of references in the vector.
|
||||
|
||||
Returns :c:macro:`MPS_RES_OK` if the root was registered
|
||||
successfully, :c:macro:`MPS_RES_MEMORY` if the new root
|
||||
description could not be allocated, or another :term:`result code`
|
||||
if there was another error.
|
||||
|
||||
The registered root description persists until it is destroyed by
|
||||
calling :c:func:`mps_root_destroy`.
|
||||
|
||||
.. _topic-root-type-pun:
|
||||
|
||||
.. warning::
|
||||
|
||||
The ``base`` argument has type ``mps_addr_t *`` (a typedef for
|
||||
``void **``) but the table of references most likely has some
|
||||
other pointer type, ``my_object *`` say. It is tempting to
|
||||
write::
|
||||
|
||||
mps_root_create_table(..., (mps_addr_t *)my_table, ...)
|
||||
|
||||
but this is :term:`type punning`, and its behaviour is not
|
||||
defined in ANSI/ISO Standard C. (GCC and Clang have a warning
|
||||
flag ``-Wstrict-aliasing`` which detects some errors of this
|
||||
form.)
|
||||
|
||||
To ensure well-defined behaviour, the pointer must be
|
||||
converted via ``void *`` (or via :c:type:`mps_addr_t`, which
|
||||
is a typedef for ``void *``), like this::
|
||||
|
||||
mps_addr_t base = my_table;
|
||||
mps_root_create_table(..., base, ...)
|
||||
|
||||
.. c:function:: mps_res_t mps_root_create_table_tagged(mps_root_t *root_o, mps_arena_t arena, mps_rank_t rank, mps_rm_t rm, mps_addr_t *base, size_t count, mps_area_scan_t scan_area, mps_word_t mask, mps_word_t pattern)
|
||||
|
||||
.. deprecated::
|
||||
|
||||
This function is equivalent to::
|
||||
|
||||
mps_root_create_area_tagged(root_o, arena, rank, mode,
|
||||
base, base + size,
|
||||
scan_area, mask, pattern)
|
||||
|
||||
Register a :term:`root` that consists of a vector of :term:`tagged
|
||||
references`.
|
||||
|
||||
``root_o`` points to a location that will hold the address of the
|
||||
new root description.
|
||||
|
||||
``arena`` is the arena.
|
||||
|
||||
``rank`` is the :term:`rank` of references in the root.
|
||||
|
||||
``rm`` is the :term:`root mode`.
|
||||
|
||||
``base`` points to a vector of tagged references.
|
||||
|
||||
``count`` is the number of tagged references in the vector.
|
||||
|
||||
``scan_area`` is an tagged area scanning function that will be
|
||||
used to scan the table, for example :c:func:`mps_scan_area_tagged`
|
||||
or :c:func:`mps_scan_area_tagged_or_zero`. See
|
||||
:ref:`topic-scanning-area`.
|
||||
|
||||
``mask`` is a :term:`bitmask` that is passed to ``scan_area`` to
|
||||
be applied to the words in the vector to locate the :term:`tag`.
|
||||
|
||||
``pattern`` is passed to ``scan_area`` to determine whether to
|
||||
consider a word as a reference. For example,
|
||||
:c:func:`mps_scan_area_tagged` will not consider any word that is
|
||||
unequal to this (after masking with ``mask``) to be a reference.
|
||||
|
||||
Returns :c:macro:`MPS_RES_OK` if the root was registered
|
||||
successfully, :c:macro:`MPS_RES_MEMORY` if the new root
|
||||
description could not be allocated, or another :term:`result code`
|
||||
if there was another error.
|
||||
|
||||
The registered root description persists until it is destroyed by
|
||||
calling :c:func:`mps_root_destroy`.
|
||||
|
||||
.. warning::
|
||||
|
||||
See the warning for :c:func:`mps_root_create_table` above.
|
||||
|
||||
.. c:function:: mps_res_t mps_root_create_table_masked(mps_root_t *root_o, mps_arena_t arena, mps_rank_t rank, mps_rm_t rm, mps_addr_t *base, size_t count, mps_word_t mask)
|
||||
|
||||
.. deprecated::
|
||||
|
||||
This function is equivalent to::
|
||||
|
||||
mps_root_create_area_tagged(root_o, arena, rank, rm,
|
||||
base, base + size,
|
||||
mps_scan_area_tagged,
|
||||
mask, 0)
|
||||
|
||||
Use :c:func:`mps_root_create_area_masked` instead, passing
|
||||
zero for the ``pattern`` argument.
|
||||
|
||||
Register a :term:`root` that consists of a vector of :term:`tagged
|
||||
references` whose pattern is zero.
|
||||
|
||||
.. c:type:: mps_res_t (*mps_reg_scan_t)(mps_ss_t ss, mps_thr_t thr, void *p, size_t s)
|
||||
|
||||
.. deprecated::
|
||||
|
||||
Use :c:func:`mps_root_create_thread` instead.
|
||||
|
||||
The type of a root scanning function for roots created with
|
||||
:c:func:`mps_root_create_reg`.
|
||||
|
||||
``ss`` is the :term:`scan state`. It must be passed to
|
||||
:c:func:`MPS_SCAN_BEGIN` and :c:func:`MPS_SCAN_END` to delimit a
|
||||
sequence of fix operations, and to the functions
|
||||
:c:func:`MPS_FIX1` and :c:func:`MPS_FIX2` when fixing a
|
||||
:term:`reference`.
|
||||
|
||||
``thr`` is the :term:`thread`.
|
||||
|
||||
``p`` and ``s`` are the corresponding values that were passed to
|
||||
:c:func:`mps_root_create_reg`.
|
||||
|
||||
Returns a :term:`result code`. If a fix function returns a value
|
||||
other than :c:macro:`MPS_RES_OK`, the scan method must return that
|
||||
value, and may return without fixing any further references.
|
||||
Generally, it is better if it returns as soon as possible. If the
|
||||
scanning is completed successfully, the function should return
|
||||
:c:macro:`MPS_RES_OK`.
|
||||
|
||||
A root scan method is called whenever the MPS needs to scan the
|
||||
root. It must then indicate references within the root by calling
|
||||
:c:func:`MPS_FIX1` and :c:func:`MPS_FIX2`.
|
||||
|
||||
.. seealso::
|
||||
|
||||
:ref:`topic-scanning`.
|
||||
|
||||
.. note::
|
||||
|
||||
:term:`Client programs` are not expected to
|
||||
write scanning functions of this type. The built-in MPS
|
||||
function :c:func:`mps_stack_scan_ambig` must be used.
|
||||
|
||||
|
||||
.. c:function:: mps_reg_scan_t mps_stack_scan_ambig
|
||||
|
||||
.. deprecated::
|
||||
|
||||
Use :c:func:`mps_root_create_thread` instead, passing
|
||||
``sizeof(mps_word_t) - 1`` for the ``mask`` argument, and
|
||||
``0`` for the ``pattern`` argument.
|
||||
|
||||
A root scanning function for :term:`ambiguous <ambiguous
|
||||
reference>` scanning of :term:`threads`, suitable for
|
||||
passing to :c:func:`mps_root_create_reg`.
|
||||
|
||||
It scans all integer registers and everything on the stack of the
|
||||
thread given, and can therefore only be used with :term:`ambiguous
|
||||
roots`. It scans locations that are more recently added to the
|
||||
stack than the location that was passed in the ``p`` argument to
|
||||
:c:func:`mps_root_create_reg`.
|
||||
|
||||
References are assumed to be represented as machine words, and are
|
||||
required to be word-aligned; unaligned values are ignored.
|
||||
|
||||
|
||||
.. index::
|
||||
single: deprecated interfaces; in version 1.113
|
||||
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue