diff options
| author | Richard Brooksby | 2012-09-11 14:51:45 +0100 |
|---|---|---|
| committer | Richard Brooksby | 2012-09-11 14:51:45 +0100 |
| commit | 4e39299392e331d65785ee4c0eb222b67461f496 (patch) | |
| tree | 649c5906a94311e222669682f543711b3425c6d2 | |
| parent | cca2921f2ddccfeafa54cb2f32e543a23b0f15a3 (diff) | |
| download | emacs-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.c | 139 |
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; | |||
| 310 | static char error_message[MSGMAX+1]; | 313 | static 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 | ||
| 315 | mps_arena_t arena; | 337 | static mps_arena_t arena; /* the arena */ |
| 316 | mps_pool_t obj_pool; | 338 | static mps_pool_t obj_pool; /* pool for ordinary Scheme objects */ |
| 317 | mps_ap_t obj_ap; | 339 | static 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 | ||
| 2336 | static mps_res_t obj_scan(mps_ss_t ss, mps_addr_t base, mps_addr_t limit) | 2373 | static 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 | ||
| 2505 | static void obj_fwd(mps_addr_t old, mps_addr_t new) | 2542 | static 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 | ||
| 2532 | static void obj_pad(mps_addr_t addr, size_t size) | 2569 | static 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 | |||
| 2606 | struct 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 | ||
| 2565 | static void mps_chat(void) | 2625 | static 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 | ||
| 2681 | struct mps_fmt_A_s obj_fmt_s = { | 2740 | static 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 | ||
| 2694 | int main(int argc, char *argv[]) | 2748 | int 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; |