aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Brooksby2012-09-11 14:51:45 +0100
committerRichard Brooksby2012-09-11 14:51:45 +0100
commit4e39299392e331d65785ee4c0eb222b67461f496 (patch)
tree649c5906a94311e222669682f543711b3425c6d2
parentcca2921f2ddccfeafa54cb2f32e543a23b0f15a3 (diff)
downloademacs-4e39299392e331d65785ee4c0eb222b67461f496.tar.gz
emacs-4e39299392e331d65785ee4c0eb222b67461f496.zip
Further improvements to documentation in the scheme example.
Copied from Perforce Change: 179418 ServerID: perforce.ravenbrook.com
-rw-r--r--mps/example/scheme/scheme.c139
1 files changed, 94 insertions, 45 deletions
diff --git a/mps/example/scheme/scheme.c b/mps/example/scheme/scheme.c
index c60efc02a26..db2b4a80e85 100644
--- a/mps/example/scheme/scheme.c
+++ b/mps/example/scheme/scheme.c
@@ -20,6 +20,8 @@
20 * collection cycles. Note that there's never any waiting for the MPS. 20 * collection cycles. Note that there's never any waiting for the MPS.
21 * THAT'S THE POINT. 21 * THAT'S THE POINT.
22 * 22 *
23 * To find the code that's particularly related to the MPS, search for %%MPS.
24 *
23 * 25 *
24 * MPS TO DO LIST 26 * MPS TO DO LIST
25 * - make the symbol table weak to show how to use weak references 27 * - make the symbol table weak to show how to use weak references
@@ -168,8 +170,9 @@ typedef struct vector_s {
168 170
169/* fwd, fwd2, pad1 -- MPS forwarding and padding objects 171/* fwd, fwd2, pad1 -- MPS forwarding and padding objects
170 * 172 *
171 * These object types are here to satisfy the MPS Format Protocol for 173 * %%MPS: These object types are here to satisfy the MPS Format Protocol
172 * format variant "A". 174 * for format variant "A". See [type mps_fmt_A_s in the reference
175 * manual](../../reference/index.html#mps_fmt_A_s).
173 * 176 *
174 * The MPS needs to be able to replace any object with forwarding object 177 * The MPS needs to be able to replace any object with forwarding object
175 * or [broken heart](http://www.memorymanagement.org/glossary/b.html#broken.heart) 178 * or [broken heart](http://www.memorymanagement.org/glossary/b.html#broken.heart)
@@ -310,11 +313,30 @@ static jmp_buf *error_handler;
310static char error_message[MSGMAX+1]; 313static char error_message[MSGMAX+1];
311 314
312 315
313/* MPS pools */ 316/* MPS globals
317 *
318 * %%MPS: These are global variables holding MPS values for use by the
319 * interpreter. In a more sophisticated integration some of these might
320 * be thread local. See `main` for where these are set up.
321 *
322 * `arena` is the global state of the MPS, and there's usually only one
323 * per process.
324 *
325 * `obj_pool` is the memory pool in which the Scheme objects are allocated.
326 * It is an instance of the Automatic Mostly Copying (AMC) pool class, which
327 * is a general-purpose garbage collector for use when there are formatted
328 * objects in the pool, but ambiguous references in thread stacks and
329 * registers.
330 *
331 * `obj_ap` is an Allocation Point that allows fast in-line non-locking
332 * allocation in a memory pool. This would usually be thread-local, but
333 * this interpreter is single-threaded. See `make_pair` etc. for how this
334 * is used with the reserve/commit protocol.
335 */
314 336
315mps_arena_t arena; 337static mps_arena_t arena; /* the arena */
316mps_pool_t obj_pool; 338static mps_pool_t obj_pool; /* pool for ordinary Scheme objects */
317mps_ap_t obj_ap; 339static mps_ap_t obj_ap; /* allocation point used to allocate objects */
318 340
319 341
320/* SUPPORT FUNCTIONS */ 342/* SUPPORT FUNCTIONS */
@@ -348,11 +370,15 @@ static void error(char *format, ...)
348 * Each object type has a function here that allocates an instance of 370 * Each object type has a function here that allocates an instance of
349 * that type. 371 * that type.
350 * 372 *
351 * These functions illustrate the two-phase MPS Allocation Point Protocol 373 * %%MPS: These functions illustrate the two-phase MPS Allocation Point
352 * with `reserve` and `commmit`. This protocol allows very fast in-line 374 * Protocol with `reserve` and `commmit`. This protocol allows very fast
353 * allocation without locking, but there is a very tiny chance that the 375 * in-line allocation without locking, but there is a very tiny chance that
354 * object must be re-initialized. In nearly all cases, however, it's 376 * the object must be re-initialized. In nearly all cases, however, it's
355 * just a pointer bump. 377 * just a pointer bump.
378 *
379 * NOTE: We could reduce duplicated code here using macros, but we want to
380 * write these out because this is code to illustrate how to use the
381 * protocol.
356 */ 382 */
357 383
358#define ALIGN(size) \ 384#define ALIGN(size) \
@@ -362,6 +388,9 @@ static obj_t make_pair(obj_t car, obj_t cdr)
362{ 388{
363 obj_t obj; 389 obj_t obj;
364 mps_addr_t addr; 390 mps_addr_t addr;
391 /* When using the allocation point protocol it is up to the client
392 code to ensure that all requests are for aligned sizes, because in
393 nearly all cases `mps_reserve` is just an increment to a pointer. */
365 size_t size = ALIGN(sizeof(pair_s)); 394 size_t size = ALIGN(sizeof(pair_s));
366 do { 395 do {
367 mps_res_t res = mps_reserve(&addr, obj_ap, size); 396 mps_res_t res = mps_reserve(&addr, obj_ap, size);
@@ -370,6 +399,12 @@ static obj_t make_pair(obj_t car, obj_t cdr)
370 obj->pair.type = TYPE_PAIR; 399 obj->pair.type = TYPE_PAIR;
371 CAR(obj) = car; 400 CAR(obj) = car;
372 CDR(obj) = cdr; 401 CDR(obj) = cdr;
402 /* `mps_commit` returns false on very rare occasions (when an MPS epoch
403 change has happened since reserve) but in those cases the object must
404 be re-initialized. It's therefore important not to do anything you
405 don't want to repeat between reserve and commit. Also, the shorter
406 the time between reserve and commit, the less likely commit is to
407 return false. */
373 } while(!mps_commit(obj_ap, addr, size)); 408 } while(!mps_commit(obj_ap, addr, size));
374 total += sizeof(pair_s); 409 total += sizeof(pair_s);
375 return obj; 410 return obj;
@@ -2310,7 +2345,8 @@ static struct {char *name; entry_t entry;} funtab[] = {
2310 2345
2311/* MPS Format 2346/* MPS Format
2312 * 2347 *
2313 * These functions satisfy the MPS Format Protocol for format variant "A". 2348 * %%MPS: These functions satisfy the MPS Format Protocol for format
2349 * variant "A".
2314 * 2350 *
2315 * In general, MPS format methods are performance critical, as they're used 2351 * In general, MPS format methods are performance critical, as they're used
2316 * on the MPS [critical path](..\..\design\critical-path.txt). 2352 * on the MPS [critical path](..\..\design\critical-path.txt).
@@ -2329,8 +2365,9 @@ static struct {char *name; entry_t entry;} funtab[] = {
2329 2365
2330/* obj_scan -- object format scanner 2366/* obj_scan -- object format scanner
2331 * 2367 *
2332 * The job of the scanner is to identify references in a contiguous group 2368 * %%MPS: The job of the scanner is to identify references in a contiguous
2333 * of objects in memory. 2369 * group of objects in memory, by passing them to the "fix" operation.
2370 * This code is highly performance critical.
2334 */ 2371 */
2335 2372
2336static mps_res_t obj_scan(mps_ss_t ss, mps_addr_t base, mps_addr_t limit) 2373static mps_res_t obj_scan(mps_ss_t ss, mps_addr_t base, mps_addr_t limit)
@@ -2411,9 +2448,9 @@ static mps_res_t obj_scan(mps_ss_t ss, mps_addr_t base, mps_addr_t limit)
2411} 2448}
2412 2449
2413 2450
2414/* obj_skip -- object format skip method 2451/* obj_skip -- object format skip method %%MPS
2415 * 2452 *
2416 * The job of skip is to return the address where the next object would 2453 * The job of `obj_skip` is to return the address where the next object would
2417 * be allocated. This isn't quite the same as the size of the object, 2454 * be allocated. This isn't quite the same as the size of the object,
2418 * since there may be some rounding according to the memory pool alignment 2455 * since there may be some rounding according to the memory pool alignment
2419 * chosen. This interpreter has chosen to align to single words. 2456 * chosen. This interpreter has chosen to align to single words.
@@ -2473,9 +2510,9 @@ static mps_addr_t obj_skip(mps_addr_t base)
2473} 2510}
2474 2511
2475 2512
2476/* obj_isfwd -- object format forwarded test 2513/* obj_isfwd -- object format forwarded test %%MPS
2477 * 2514 *
2478 * The job of obj_isfwd is to detect whether an object has been replaced 2515 * The job of `obj_isfwd` is to detect whether an object has been replaced
2479 * by a forwarding object, and return the address of the new copy if it has, 2516 * by a forwarding object, and return the address of the new copy if it has,
2480 * otherwise NULL. Note that this will return NULL for padding objects 2517 * otherwise NULL. Note that this will return NULL for padding objects
2481 * because their `fwd` field is set to NULL. 2518 * because their `fwd` field is set to NULL.
@@ -2494,12 +2531,12 @@ static mps_addr_t obj_isfwd(mps_addr_t addr)
2494} 2531}
2495 2532
2496 2533
2497/* obj_fwd -- object format forwarding method 2534/* obj_fwd -- object format forwarding method %%MPS
2498 * 2535 *
2499 * The job of obj_fwd is to replace an object by a forwarding object that 2536 * The job of `obj_fwd` is to replace an object by a forwarding object that
2500 * points at a new copy of the object. The object must be detected by 2537 * points at a new copy of the object. The object must be detected by
2501 * `obj_isfwd`. In this case, we have to be careful to replace two-word 2538 * `obj_isfwd`. In this case, we have to be careful to replace two-word
2502 * objects with a FWD2 object, because the FWD object won't fit. 2539 * objects with a `FWD2` object, because the `FWD` object won't fit.
2503 */ 2540 */
2504 2541
2505static void obj_fwd(mps_addr_t old, mps_addr_t new) 2542static void obj_fwd(mps_addr_t old, mps_addr_t new)
@@ -2519,14 +2556,14 @@ static void obj_fwd(mps_addr_t old, mps_addr_t new)
2519} 2556}
2520 2557
2521 2558
2522/* obj_pad -- object format padding method 2559/* obj_pad -- object format padding method %%MPS
2523 * 2560 *
2524 * The job of obj_pad is to fill in a block of memory with a padding 2561 * The job of `obj_pad` is to fill in a block of memory with a padding
2525 * object that will be skipped by `obj_scan` or `obj_skip` but does 2562 * object that will be skipped by `obj_scan` or `obj_skip` but does
2526 * nothing else. Because we've chosen to align to single words, we may 2563 * nothing else. Because we've chosen to align to single words, we may
2527 * have to pad a single word, so we have a special single-word padding 2564 * have to pad a single word, so we have a special single-word padding
2528 * object, PAD1 for that purpose. Otherwise we can use forwarding objects 2565 * object, `PAD1` for that purpose. Otherwise we can use forwarding
2529 * with their `fwd` fields set to NULL. 2566 * objects with their `fwd` fields set to `NULL`.
2530 */ 2567 */
2531 2568
2532static void obj_pad(mps_addr_t addr, size_t size) 2569static void obj_pad(mps_addr_t addr, size_t size)
@@ -2546,9 +2583,9 @@ static void obj_pad(mps_addr_t addr, size_t size)
2546} 2583}
2547 2584
2548 2585
2549/* obj_copy -- object format copy method 2586/* obj_copy -- object format copy method %%MPS
2550 * 2587 *
2551 * The job of obj_copy is to make a copy of an object. 2588 * The job of `obj_copy` is to make a copy of an object.
2552 * TODO: Explain why this exists. 2589 * TODO: Explain why this exists.
2553 */ 2590 */
2554 2591
@@ -2560,7 +2597,30 @@ static void obj_copy(mps_addr_t old, mps_addr_t new)
2560} 2597}
2561 2598
2562 2599
2563/* mps_chat -- get and display MPS messages */ 2600/* obj_fmt_s -- object format parameter structure %%MPS
2601 *
2602 * This is simply a gathering of the object format methods and the chosen
2603 * pool alignment for passing to `mps_fmt_create_A`.
2604 */
2605
2606struct mps_fmt_A_s obj_fmt_s = {
2607 sizeof(mps_word_t),
2608 obj_scan,
2609 obj_skip,
2610 obj_copy,
2611 obj_fwd,
2612 obj_isfwd,
2613 obj_pad
2614};
2615
2616
2617/* mps_chat -- get and display MPS messages %%MPS
2618 *
2619 * The MPS message protocol allows the MPS to communicate various things
2620 * to the client code. Because the MPS may run asynchronously the client
2621 * must poll the MPS to pick up messages. This function shows how this
2622 * is done.
2623 */
2564 2624
2565static void mps_chat(void) 2625static void mps_chat(void)
2566{ 2626{
@@ -2589,7 +2649,7 @@ static void mps_chat(void)
2589} 2649}
2590 2650
2591 2651
2592/* start -- the main program 2652/* start -- the main program %%MPS
2593 * 2653 *
2594 * This is the main body of the Scheme interpreter program, invoked by 2654 * This is the main body of the Scheme interpreter program, invoked by
2595 * `mps_tramp` so that its stack and exception handling can be managed 2655 * `mps_tramp` so that its stack and exception handling can be managed
@@ -2672,35 +2732,24 @@ static void *start(void *p, size_t s)
2672} 2732}
2673 2733
2674 2734
2675/* obj_fmt_s -- object format parameter structure 2735/* obj_gen_params -- initial setup for generational GC %%MPS
2676 * 2736 *
2677 * This is simply a gathering of the object format methods and the chosen 2737 * FIXME: explain this
2678 * pool alignment for passing to `mps_fmt_create_A`.
2679 */ 2738 */
2680 2739
2681struct mps_fmt_A_s obj_fmt_s = { 2740static mps_gen_param_s obj_gen_params[] = {
2682 sizeof(mps_word_t), 2741 { 150, 0.85 },
2683 obj_scan, 2742 { 170, 0.45 }
2684 obj_skip,
2685 obj_copy,
2686 obj_fwd,
2687 obj_isfwd,
2688 obj_pad
2689}; 2743};
2690 2744
2691 2745
2692/* main -- program entry point and MPS initialization */ 2746/* main -- program entry point and MPS initialization %%MPS */
2693 2747
2694int main(int argc, char *argv[]) 2748int main(int argc, char *argv[])
2695{ 2749{
2696 mps_res_t res; 2750 mps_res_t res;
2697 mps_chain_t obj_chain; 2751 mps_chain_t obj_chain;
2698 mps_fmt_t obj_fmt; 2752 mps_fmt_t obj_fmt;
2699 /* FIXME: explain this */
2700 mps_gen_param_s obj_gen_params[] = {
2701 { 150, 0.85 },
2702 { 170, 0.45 }
2703 };
2704 mps_thr_t thread; 2753 mps_thr_t thread;
2705 mps_root_t reg_root; 2754 mps_root_t reg_root;
2706 void *r; 2755 void *r;