On Dec 8, 2013, at 2:44 PM, Bradley Lucier lucier@math.purdue.edu wrote:
So, Marc, spill the beans! There are thousands and thousands of lines of new code in this release; what's new? What can we play with here?
This release represents the latest month of work where the runtime system has been refactored to support multiple VMs and multiple threaded VMs (with OS threads). Data structures had to be modified to clarify what is shared between VMs, and what is specific to each "processor" in each VM instance. An abstraction layer was added to interface to the operating system's thread system. The linker was also changed to allow a VM to only initialize the modules it requires. Not much of this work translates to user visible features at this point, but it does put in place a new organization of the runtime system that is necessary for a parallel Gambit. Given that the Gambit compiler's code generation changed (to support the new linker), it was necessary to do a "release", otherwise it would not be possible to build Gambit from the sources on the repo. I'm also interested in having feedback from people building this new release of Gambit. Please report any problems building Gambit on your computer.
One feature that is user visible, and possibly interesting for developers of large applications, is the ability to link modules into an executable, but not "load" these modules when the program is started. This can make the startup of the application faster and use less memory. This is achieved with the -nopreload linker option, the special form (##require-module <name>) and the procedure (##load-required-module '<name>), where <name> is a symbol naming a module.
The form (##require-module <name>) can be placed anywhere a definition is allowed. For example it could be at the file's top-level, inside of a function definition, or the head of a let body. This form adds the call (##load-required-module '<name>) at the *top* of the file. The procedure ##load-required-module causes a linked module to be loaded if it has not previously been loaded. By default the linker loads all the linked modules when the program is started (what I call "preloading" of a module). The linker now has the option -nopreload that can be placed anywhere on the command line to prevent the preloading of the following modules. Here's an example:
% cat a.scm (pp 'hello-from-a.scm)
(define (double x) (* 2 x)) % cat b.scm (pp 'hello-from-b.scm)
(define (fun x) (##require-module a) (pp (double x))) % cat c.scm (pp 'hello-from-c.scm)
(thread-sleep! 2)
(##load-required-module 'b)
(fun 100) % gsc -exe a.scm b.scm c.scm % ./c hello-from-a.scm hello-from-b.scm hello-from-c.scm <2 second pause> 200
Note that the invocation of gsc without the -nopreload option gives the same behavior as previous versions of Gambit: all modules are preloaded in a left to right order.
Here's what happens when the preloading is disabled:
% gsc -exe -nopreload a.scm b.scm c.scm % ./c hello-from-c.scm <2 second pause> hello-from-a.scm hello-from-b.scm 200
Here the program only loads module c (the "main" program is always the last module). It is module c that explicitly requests the loading of module b by calling (##load-required-module 'b). However, since module b has a dependency on module a (in function fun), module b will require the loading of module a before its body is executed. So module a's body is executed before module b's body.
These features form the basis for constructing a module system.
Marc