diff --git a/mps/design/arena.txt b/mps/design/arena.txt index 65b41f74ccd..a1fae81ce5e 100644 --- a/mps/design/arena.txt +++ b/mps/design/arena.txt @@ -233,14 +233,14 @@ associating their own data with each allocation grain. _`.tract.structure`: The tract structure definition looks like this:: typedef struct TractStruct { /* Tract structure */ - Pool pool; /* MUST BE FIRST (design.mps.arena.tract.field.pool) */ + PagePoolUnion pool; /* MUST BE FIRST (design.mps.arena.tract.field.pool) */ void *p; /* pointer for use of owning pool */ Addr base; /* Base address of the tract */ TraceSet white : TRACE_MAX; /* traces for which tract is white */ unsigned int hasSeg : 1; /* does tract have a seg in p? */ } TractStruct; -_`.tract.field.pool`: The pool field indicates to which pool the tract +_`.tract.field.pool`: The pool.pool field indicates to which pool the tract has been allocated (`.req.fun.trans.pool`_). Tracts are only valid when they are allocated to pools. When tracts are not allocated to pools, arena classes are free to reuse tract objects in undefined @@ -546,6 +546,8 @@ Document History - 2013-03-11 GDR_ Converted to reStructuredText. +- 2014-02-17 RB_ Updated first field of tract structure. + .. _RB: http://www.ravenbrook.com/consultants/rb/ .. _GDR: http://www.ravenbrook.com/consultants/gdr/ diff --git a/mps/design/arenavm.txt b/mps/design/arenavm.txt index ffe97432aa1..92b24d8234d 100644 --- a/mps/design/arenavm.txt +++ b/mps/design/arenavm.txt @@ -167,13 +167,7 @@ the base address in the VM. Namely: - base address to index: ``index = (base-address - arena-base) / page-size`` _`.table.page.partial`: The table is partially mapped on an -"as-needed" basis. The function ``unusedTablePages()`` identifies -entirely unused pages occupied by the page table itself (that is, -those pages of the page table which are occupied by ``PageStruct`` -objects which all describe free pages). Tract allocation and freeing -use this function to map and unmap the page table with no hysteresis. -(There is restriction on the parameters you may pass to -``unusedTablePages()``.) +"as-needed" basis using the SparseArray abstract type. _`.table.page.tract`: Each page table entry contains a tract, which is only valid if it is allocated to a pool. If it is not allocated to a @@ -215,6 +209,9 @@ Document History - 2013-05-24 GDR_ Converted to reStructuredText. +- 2014-02-17 RB_ Updated to note use of SparseArray rather than direct +management of page table mapping. + .. _RB: http://www.ravenbrook.com/consultants/rb/ .. _GDR: http://www.ravenbrook.com/consultants/gdr/ diff --git a/mps/manual/source/guide/lang.rst b/mps/manual/source/guide/lang.rst index 1b7877a90ac..aa18ac80174 100644 --- a/mps/manual/source/guide/lang.rst +++ b/mps/manual/source/guide/lang.rst @@ -673,55 +673,6 @@ code must be added to ``obj_scan`` and ``obj_skip``:: :ref:`topic-format`. -.. index:: - single: generation chain - single: chain; generation - single: Scheme; generation chain - -Generation chains ------------------ - -The AMC pool requires not only an object format but a -:term:`generation chain`. This specifies the generation structure of -the :term:`generational garbage collection`. - -You create a generation chain by constructing an array of structures -of type :c:type:`mps_gen_param_s`, one for each generation, and -passing them to :c:func:`mps_chain_create`. Each of these structures -contains two values, the *capacity* of the generation in -:term:`kilobytes`, and the *mortality*, the proportion of -objects in the generation that you expect to survive a collection of -that generation. - -These numbers are *hints* to the MPS that it may use to make decisions -about when and what to collect: nothing will go wrong (other than -suboptimal performance) if you make poor choices. Making good choices -for the capacity and mortality of each generation is not easy, and is postponed to the chapter :ref:`guide-perf`. - -Here's the code for creating the generation chain for the toy Scheme -interpreter:: - - mps_gen_param_s obj_gen_params[] = { - { 150, 0.85 }, - { 170, 0.45 }, - }; - - res = mps_chain_create(&obj_chain, - arena, - LENGTH(obj_gen_params), - obj_gen_params); - if (res != MPS_RES_OK) error("Couldn't create obj chain"); - -Note that these numbers have have been deliberately chosen to be -small, so that the MPS is forced to collect often, so that you can see -it working. Don't just copy these numbers unless you also want to see -frequent garbage collections! - -.. topics:: - - :ref:`topic-collection`. - - .. index:: single: pool; creating single: Scheme; pool @@ -748,25 +699,10 @@ Second, the :term:`object format`:: } MPS_ARGS_END(args); if (res != MPS_RES_OK) error("Couldn't create obj format"); -Third, the :term:`generation chain`:: - - mps_gen_param_s obj_gen_params[] = { - { 150, 0.85 }, - { 170, 0.45 }, - }; - - mps_chain_t obj_chain; - res = mps_chain_create(&obj_chain, - arena, - LENGTH(obj_gen_params), - obj_gen_params); - if (res != MPS_RES_OK) error("Couldn't create obj chain"); - And finally the :term:`pool`:: mps_pool_t obj_pool; MPS_ARGS_BEGIN(args) { - MPS_ARGS_ADD(args, MPS_KEY_CHAIN, obj_chain); MPS_ARGS_ADD(args, MPS_KEY_FORMAT, obj_fmt); MPS_ARGS_DONE(args); res = mps_pool_create_k(&obj_pool, arena, mps_class_amc(), args); @@ -1206,10 +1142,12 @@ tracking down the causes, appear in the chapter :ref:`guide-debug`. Tidying up ---------- -When your program is done with the MPS, it's good practice to tear -down all the MPS data structures. This causes the MPS to check the -consistency of its data structures and report any problems it -detects. It also causes the MPS to flush its :term:`telemetry stream`. +When your program is done with the MPS, it's good practice to +:term:`park ` the arena (by calling +:c:func:`mps_arena_park`) and then tear down all the MPS data +structures. This causes the MPS to check the consistency of its data +structures and report any problems it detects. It also causes the MPS +to flush its :term:`telemetry stream`. MPS data structures must be destroyed or deregistered in the reverse order to that in which they were registered or created. So you must @@ -1218,16 +1156,15 @@ destroy all :term:`allocation points` created in a were created in an :term:`arena` before destroying the arena, and so on. -Here's the tear-down code from the toy Scheme interpreter:: +For example:: - mps_arena_park(arena); - mps_ap_destroy(obj_ap); - mps_pool_destroy(obj_pool); - mps_chain_destroy(obj_chain); - mps_fmt_destroy(obj_fmt); - mps_root_destroy(reg_root); - mps_thread_dereg(thread); - mps_arena_destroy(arena); + mps_arena_park(arena); /* ensure no collection is running */ + mps_ap_destroy(obj_ap); /* destroy ap before pool */ + mps_pool_destroy(obj_pool); /* destroy pool before fmt */ + mps_fmt_destroy(obj_fmt); /* destroy fmt before arena */ + mps_root_destroy(reg_root); /* destroy root before arena */ + mps_thread_dereg(thread); /* deregister thread before arena */ + mps_arena_destroy(arena); /* last of all */ What next? diff --git a/mps/manual/source/pool/amc.rst b/mps/manual/source/pool/amc.rst index 4ef88303f81..beef282c141 100644 --- a/mps/manual/source/pool/amc.rst +++ b/mps/manual/source/pool/amc.rst @@ -31,10 +31,6 @@ following tendencies will be efficiently exploited by an AMC pool: - objects that don't die young will live a long time. -In the pool's :term:`generation chain`, specify the capacity and -mortality of generations 0 to *n*\−1. Survivors from generation *n*\−1 -get promoted into an arena-wide "top" generation. - .. index:: single: AMC; properties @@ -57,6 +53,9 @@ AMC properties * Garbage collections are scheduled automatically. See :ref:`topic-collection-schedule`. +* Uses :term:`generational garbage collection`: blocks are promoted + from generation to generation in the pool's chain. + * Blocks may contain :term:`exact references` to blocks in the same or other pools (but may not contain :term:`ambiguous references` or :term:`weak references (1)`, and may not use :term:`remote @@ -106,7 +105,7 @@ AMC interface Mostly-Copying) :term:`pool`. When creating an AMC pool, :c:func:`mps_pool_create_k` requires - two :term:`keyword arguments`: + one :term:`keyword argument`: * :c:macro:`MPS_KEY_FORMAT` (type :c:type:`mps_fmt_t`) specifies the :term:`object format` for the objects allocated in the pool. @@ -114,13 +113,15 @@ AMC interface method`, a :term:`forward method`, an :term:`is-forwarded method` and a :term:`padding method`. + It accepts one optional keyword argument: + * :c:macro:`MPS_KEY_CHAIN` (type :c:type:`mps_chain_t`) specifies - the :term:`generation chain` for the pool. + the :term:`generation chain` for the pool. If not specified, the + pool will use the arena's default chain. For example:: MPS_ARGS_BEGIN(args) { - MPS_ARGS_ADD(args, MPS_KEY_CHAIN, chain); MPS_ARGS_ADD(args, MPS_KEY_FORMAT, fmt); MPS_ARGS_DONE(args); res = mps_pool_create_k(&pool, arena, mps_class_amc(), args); diff --git a/mps/manual/source/pool/amcz.rst b/mps/manual/source/pool/amcz.rst index 45444e07404..8f72af9050a 100644 --- a/mps/manual/source/pool/amcz.rst +++ b/mps/manual/source/pool/amcz.rst @@ -60,7 +60,7 @@ AMCZ interface Mostly-Copying Zero-rank) :term:`pool`. When creating an AMCZ pool, :c:func:`mps_pool_create_k` requires - two :term:`keyword arguments`: + one :term:`keyword argument`: * :c:macro:`MPS_KEY_FORMAT` (type :c:type:`mps_fmt_t`) specifies the :term:`object format` for the objects allocated in the pool. @@ -68,13 +68,15 @@ AMCZ interface method`, an :term:`is-forwarded method` and a :term:`padding method`. + It accepts one optional keyword argument: + * :c:macro:`MPS_KEY_CHAIN` (type :c:type:`mps_chain_t`) specifies - the :term:`generation chain` for the pool. + the :term:`generation chain` for the pool. If not specified, the + pool will use the arena's default chain. For example:: MPS_ARGS_BEGIN(args) { - MPS_ARGS_ADD(args, MPS_KEY_CHAIN, chain); MPS_ARGS_ADD(args, MPS_KEY_FORMAT, fmt); MPS_ARGS_DONE(args); res = mps_pool_create_k(&pool, arena, mps_class_amcz(), args); @@ -85,7 +87,7 @@ AMCZ interface When using :c:func:`mps_pool_create`, pass the format and chain like this:: - mps_res_t mps_pool_create(mps_pool_t *pool_o, mps_arena_t arena, - mps_class_t mps_class_amcz(), - mps_fmt_t fmt, - mps_chain_t chain) + mps_res_t mps_pool_create(mps_pool_t *pool_o, mps_arena_t arena, + mps_class_t mps_class_amcz(), + mps_fmt_t fmt, + mps_chain_t chain) diff --git a/mps/manual/source/pool/ams.rst b/mps/manual/source/pool/ams.rst index 7de550257d4..922d9d8e366 100644 --- a/mps/manual/source/pool/ams.rst +++ b/mps/manual/source/pool/ams.rst @@ -17,11 +17,6 @@ management>` but :term:`non-moving ` :term:`pool class`. It should be used instead of :ref:`pool-amc` for blocks that need to be automatically managed, but cannot be moved. -AMS does not use :term:`generational garbage collection`, but when -creating a pool you use a :term:`generation chain` to specify the -capacity and mortality of a single "generation". These numbers are -used to schedule the collection of the whole pool. - .. note:: AMS is likely to be useful as a step in integrating a program with @@ -56,6 +51,9 @@ AMS properties * Garbage collections are scheduled automatically. See :ref:`topic-collection-schedule`. +* Does not use :term:`generational garbage collection`, so blocks are + never promoted out of the generation in which they are allocated. + * Blocks may contain :term:`exact references` to blocks in the same or other pools, or :term:`ambiguous references` (if the :c:macro:`MPS_KEY_AMS_SUPPORT_AMBIGUOUS` keyword argument is set to @@ -116,6 +114,21 @@ AMS interface the :term:`generation chain` for the pool. It must have a single generation. + It accepts three optional keyword arguments: + + * :c:macro:`MPS_KEY_CHAIN` (type :c:type:`mps_chain_t`) specifies + the :term:`generation chain` for the pool. If not specified, the + pool will use the arena's default chain. + + * :c:macro:`MPS_KEY_GEN` (type :c:type:`unsigned`) specifies the + :term:`generation` in the chain into which new objects will be + allocated. If you pass your own chain, then this defaults to + ``0``, but if you didn't (and so use the arena's default chain), + then an appropriate generation is used. + + Note that AWL does not use generational garbage collection, so + blocks remain in this generation and are not promoted. + * :c:macro:`MPS_KEY_AMS_SUPPORT_AMBIGUOUS` (type :c:type:`mps_bool_t`, default false) specifies whether references may be ambiguous. @@ -123,7 +136,6 @@ AMS interface For example:: MPS_ARGS_BEGIN(args) { - MPS_ARGS_ADD(args, MPS_KEY_CHAIN, chain); MPS_ARGS_ADD(args, MPS_KEY_FORMAT, fmt); MPS_ARGS_ADD(args, MPS_KEY_AMS_SUPPORT_AMBIGUOUS, 1); MPS_ARGS_DONE(args); @@ -132,8 +144,8 @@ AMS interface .. deprecated:: starting with version 1.112. - When using :c:func:`mps_pool_create`, pass the format and - chain like this:: + When using :c:func:`mps_pool_create`, pass the format, + chain, and ambiguous flag like this:: mps_res_t mps_pool_create(mps_pool_t *pool_o, mps_arena_t arena, mps_class_t mps_class_ams(), diff --git a/mps/manual/source/pool/awl.rst b/mps/manual/source/pool/awl.rst index ebb5121aeaf..b187965bb0c 100644 --- a/mps/manual/source/pool/awl.rst +++ b/mps/manual/source/pool/awl.rst @@ -70,6 +70,9 @@ AWL properties * Garbage collections are scheduled automatically. See :ref:`topic-collection-schedule`. +* Does not use :term:`generational garbage collection`, so blocks are + never promoted out of the generation in which they are allocated. + * Blocks may contain :term:`exact references` or :term:`weak references (1)` to blocks in the same or other pools (but may not contain :term:`ambiguous references`, and may not use :term:`remote @@ -323,6 +326,21 @@ AWL interface how to find the :term:`dependent object` for an object in the pool. + It accepts two optional keyword arguments: + + * :c:macro:`MPS_KEY_CHAIN` (type :c:type:`mps_chain_t`) specifies + the :term:`generation chain` for the pool. If not specified, the + pool will use the arena's default chain. + + * :c:macro:`MPS_KEY_GEN` (type :c:type:`unsigned`) specifies the + :term:`generation` in the chain into which new objects will be + allocated. If you pass your own chain, then this defaults to + ``0``, but if you didn't (and so use the arena's default chain), + then an appropriate generation is used. + + Note that AWL does not use generational garbage collection, so + blocks remain in this generation and are not promoted. + For example:: MPS_ARGS_BEGIN(args) { diff --git a/mps/manual/source/pool/intro.rst b/mps/manual/source/pool/intro.rst index 15827667643..ea2a03ce562 100644 --- a/mps/manual/source/pool/intro.rst +++ b/mps/manual/source/pool/intro.rst @@ -118,6 +118,7 @@ Alignment? [5]_ conf conf conf conf conf Dependent objects? [8]_ no --- no yes --- --- --- --- --- no May use remote references? [9]_ no --- no no --- --- --- --- --- no Blocks are automatically managed? [10]_ yes yes yes yes yes no no no no no +Blocks are promoted between generations yes yes no no no --- --- --- --- --- Blocks are manually managed? [10]_ no no no no no yes yes yes yes yes Blocks are scanned? [11]_ yes no yes yes no no no no no yes Blocks support base pointers only? [12]_ yes yes yes yes yes --- --- --- --- yes diff --git a/mps/manual/source/pool/lo.rst b/mps/manual/source/pool/lo.rst index ffe36ba3fff..5814e36e0a7 100644 --- a/mps/manual/source/pool/lo.rst +++ b/mps/manual/source/pool/lo.rst @@ -59,6 +59,9 @@ LO properties * Garbage collections are scheduled automatically. See :ref:`topic-collection-schedule`. +* Does not use :term:`generational garbage collection`, so blocks are + never promoted out of the generation in which they are allocated. + * Blocks may not contain :term:`references` to blocks in automatically managed pools. @@ -105,13 +108,28 @@ LO interface Return the :term:`pool class` for an LO (Leaf Object) :term:`pool`. - When creating an LO pool, :c:func:`mps_pool_create_k` require one + When creating an LO pool, :c:func:`mps_pool_create_k` requires one :term:`keyword argument`: * :c:macro:`MPS_KEY_FORMAT` (type :c:type:`mps_fmt_t`) specifies the :term:`object format` for the objects allocated in the pool. The format must provide a :term:`skip method`. + It accepts two optional keyword arguments: + + * :c:macro:`MPS_KEY_CHAIN` (type :c:type:`mps_chain_t`) specifies + the :term:`generation chain` for the pool. If not specified, the + pool will use the arena's default chain. + + * :c:macro:`MPS_KEY_GEN` (type :c:type:`unsigned`) specifies the + :term:`generation` in the chain into which new objects will be + allocated. If you pass your own chain, then this defaults to + ``0``, but if you didn't (and so use the arena's default chain), + then an appropriate generation is used. + + Note that LO does not use generational garbage collection, so + blocks remain in this generation and are not promoted. + For example:: MPS_ARGS_BEGIN(args) { diff --git a/mps/manual/source/topic/collection.rst b/mps/manual/source/topic/collection.rst index 5a3261238d2..de5629e52d6 100644 --- a/mps/manual/source/topic/collection.rst +++ b/mps/manual/source/topic/collection.rst @@ -28,10 +28,29 @@ capable of collecting many automatically managed pools simultaneously. Generation chains ----------------- -A :term:`generation chain` describes the structure of the -:term:`generations` in a set of :term:`automatically managed -` :term:`pools`. The same generation -chain should be used for all pools whose blocks live and die together. +A :term:`generation chain` describes a sequence of :term:`generations` +used by a set of :term:`automatically managed ` :term:`pools`. + +A generation is a set of blocks that are managed together by the +:term:`garbage collector`: they are :term:`condemned ` +together, and in :term:`moving ` pools they are +moved together. If two pools allocate blocks that are expected to live +and die together, then it is efficient for them to share a chain. + +Typically blocks are allocated in the first generation in the chain, +the :term:`nursery generation` (though you can change this using the +:c:macro:`MPS_KEY_GEN` keyword argument to :c:func:`mps_pool_create`), +and each time a block survives one collection then it is +:term:`promoted ` to the next generation. Thus a generation +contains a set of blocks of similar ages. + +By default, all pools in an arena share the same generation chain +("the arena's default generation chain"), but if this doesn't meet +your requirements, then when creating an automatically managed pool, +you can choose which chain it should use by passing the +:c:macro:`MPS_KEY_CHAIN` keyword argument to +:c:func:`mps_pool_create`. Create a generation chain by preparing an array of :c:type:`mps_gen_param_s` structures giving the *capacity* (in @@ -59,8 +78,9 @@ For example:: .. c:type:: mps_chain_t - The type of :term:`generation chains`. A - generation chain describes the structure of :term:`generations` in a :term:`pool`. + The type of :term:`generation chains`. A generation chain + describes the structure of :term:`generations` in a set of + :term:`pools`. .. c:type:: mps_gen_param_s @@ -260,7 +280,7 @@ Garbage collection messages generated the message; * :c:func:`mps_message_gc_not_condemned_size` returns the - approximate size of the set of objects that were in collected + approximate size of the set of blocks that were in collected :term:`pools`, but were not condemned in the garbage collection that generated the message. @@ -298,7 +318,7 @@ Garbage collection messages not yet discarded. It must be a garbage collection message: see :c:func:`mps_message_type_gc`. - The "live size" property is the total size of the set of objects + The "live size" property is the total size of the set of blocks that survived the :term:`garbage collection` that generated the message. @@ -318,7 +338,7 @@ Garbage collection messages :c:func:`mps_message_type_gc`. The "not condemned size" property is the approximate size of the - set of objects that were in collected :term:`pools`, but + set of blocks that were in collected :term:`pools`, but were not in the :term:`condemned set` in the :term:`garbage collection` that generated the message. diff --git a/mps/manual/source/topic/debugging.rst b/mps/manual/source/topic/debugging.rst index 93f069d3c5d..980e982da60 100644 --- a/mps/manual/source/topic/debugging.rst +++ b/mps/manual/source/topic/debugging.rst @@ -74,7 +74,6 @@ For example:: MPS_ARGS_BEGIN(args) { MPS_ARGS_ADD(args, MPS_KEY_POOL_DEBUG_OPTIONS, &debug_options); MPS_ARGS_ADD(args, MPS_KEY_FORMAT, &fmt); - MPS_ARGS_ADD(args, MPS_KEY_CHAIN, &chain); MPS_ARGS_DONE(args); res = mps_pool_create_k(&pool, arena, mps_class_ams_debug(), args); } MPS_ARGS_END(args); diff --git a/mps/manual/source/topic/keyword.rst b/mps/manual/source/topic/keyword.rst index d4150eedbd3..dac5cce2626 100644 --- a/mps/manual/source/topic/keyword.rst +++ b/mps/manual/source/topic/keyword.rst @@ -93,7 +93,7 @@ now :c:macro:`MPS_KEY_ARGS_END`. :c:macro:`MPS_KEY_ARENA_CL_BASE` :c:type:`mps_addr_t` ``addr`` :c:func:`mps_arena_class_cl` :c:macro:`MPS_KEY_ARENA_SIZE` :c:type:`size_t` ``size`` :c:func:`mps_arena_class_vm`, :c:func:`mps_arena_class_cl` :c:macro:`MPS_KEY_AWL_FIND_DEPENDENT` ``void *(*)(void *)`` ``addr_method`` :c:func:`mps_class_awl` - :c:macro:`MPS_KEY_CHAIN` :c:type:`mps_chain_t` ``chain`` :c:func:`mps_class_amc`, :c:func:`mps_class_amcz`, :c:func:`mps_class_ams` + :c:macro:`MPS_KEY_CHAIN` :c:type:`mps_chain_t` ``chain`` :c:func:`mps_class_amc`, :c:func:`mps_class_amcz`, :c:func:`mps_class_ams`, :c:func:`mps_class_awl`, :c:func:`mps_class_lo` :c:macro:`MPS_KEY_EXTEND_BY` :c:type:`size_t` ``size`` :c:func:`mps_class_mfs`, :c:func:`mps_class_mv`, :c:func:`mps_class_mvff` :c:macro:`MPS_KEY_FMT_ALIGN` :c:type:`mps_align_t` ``align`` :c:func:`mps_fmt_create_k` :c:macro:`MPS_KEY_FMT_CLASS` :c:type:`mps_fmt_class_t` ``fmt_class`` :c:func:`mps_fmt_create_k` @@ -104,6 +104,7 @@ now :c:macro:`MPS_KEY_ARGS_END`. :c:macro:`MPS_KEY_FMT_SCAN` :c:type:`mps_fmt_scan_t` ``fmt_scan`` :c:func:`mps_fmt_create_k` :c:macro:`MPS_KEY_FMT_SKIP` :c:type:`mps_fmt_skip_t` ``fmt_skip`` :c:func:`mps_fmt_create_k` :c:macro:`MPS_KEY_FORMAT` :c:type:`mps_fmt_t` ``format`` :c:func:`mps_class_amc`, :c:func:`mps_class_amcz`, :c:func:`mps_class_ams`, :c:func:`mps_class_awl`, :c:func:`mps_class_lo` , :c:func:`mps_class_snc` + :c:macro:`MPS_KEY_GEN` :c:type:`unsigned` ``u`` :c:func:`mps_class_ams`, :c:func:`mps_class_awl`, :c:func:`mps_class_lo` :c:macro:`MPS_KEY_MAX_SIZE` :c:type:`size_t` ``size`` :c:func:`mps_class_mv` :c:macro:`MPS_KEY_MEAN_SIZE` :c:type:`size_t` ``size`` :c:func:`mps_class_mv`, :c:func:`mps_class_mvt`, :c:func:`mps_class_mvff` :c:macro:`MPS_KEY_MFS_UNIT_SIZE` :c:type:`size_t` ``size`` :c:func:`mps_class_mfs` diff --git a/mps/procedure/branch-merge.rst b/mps/procedure/branch-merge.rst index be51e87fae6..232a5a925b4 100644 --- a/mps/procedure/branch-merge.rst +++ b/mps/procedure/branch-merge.rst @@ -23,11 +23,11 @@ This document contains procedures and checklists for branching and merging durin #. If you are creating a development branch to fix a problem, make sure that there's a job recording the problem. -#. Create a branch specification. +#. Create a branch specification. For example:: p4 branch mps/branch/2013-08-21/lii6ll - The specification should look something like this:: + The specification should look like this:: Branch: mps/branch/2013-08-21/lii6ll @@ -37,7 +37,7 @@ This document contains procedures and checklists for branching and merging durin View: //info.ravenbrook.com/project/mps/master/... //info.ravenbrook.com/project/mps/branch/2013-08-21/lii6ll/... -#. If you're working on a problem that's specific to customer, then +#. If you're working on a problem that's specific to a customer, then map the mainline for that customer rather than the master sources:: View: