Next: , Previous: , Up: Compiling to the Virtual Machine   [Contents][Index]

9.4.6 Bytecode and Objcode

Finally, the raw bytes. There are actually two different “languages” here, corresponding to two different ways to represent the bytes.

“Bytecode” represents code as uniform byte vectors, useful for structuring and destructuring code on the Scheme level. Bytecode is the next step down from assembly:

scheme@(guile-user)> (compile '(+ 32 10) #:to 'bytecode)
⇒ #vu8(8 0 0 0 25 0 0 0            ; Header.
       95 0                            ; Prologue.
       10 32 10 10 148 66 17           ; Actual code.
       0 0 0 0 0 0 0 9                 ; Metadata thunk.
       9 10 2 10 8 11 18 0 3 18 0 1 18 0 3 66)

“Objcode” is bytecode, but mapped directly to a C structure, struct scm_objcode:

struct scm_objcode {
  scm_t_uint32 len;
  scm_t_uint32 metalen;
  scm_t_uint8 base[0];

As one might imagine, objcode imposes a minimum length on the bytecode. Also, the len and metalen fields are in native endianness, which makes objcode (and bytecode) system-dependent.

Objcode also has a couple of important efficiency hacks. First, objcode may be mapped directly from disk, allowing compiled code to be loaded quickly, often from the system’s disk cache, and shared among multiple processes. Secondly, objcode may be embedded in other objcode, allowing procedures to have the text of other procedures inlined into their bodies, without the need for separate allocation of the code. Of course, the objcode object itself does need to be allocated.

Procedures related to objcode are defined in the (system vm objcode) module.

Scheme Procedure: objcode? obj
C Function: scm_objcode_p (obj)

Returns #f if obj is object code, #f otherwise.

Scheme Procedure: bytecode->objcode bytecode
C Function: scm_bytecode_to_objcode (bytecode)

Makes a bytecode object from bytecode, which should be a bytevector. See Bytevectors.

Scheme Variable: load-objcode file
C Function: scm_load_objcode (file)

Load object code from a file named file. The file will be mapped into memory via mmap, so this is a very fast operation.

On disk, object code has an sixteen-byte cookie prepended to it, to prevent accidental loading of arbitrary garbage.

Scheme Variable: write-objcode objcode file
C Function: scm_write_objcode (objcode)

Write object code out to a file, prepending the sixteen-byte cookie.

Scheme Variable: objcode->bytecode objcode
C Function: scm_objcode_to_bytecode (objcode)

Copy object code out to a bytevector for analysis by Scheme.

The following procedure is actually in (system vm program), but we’ll mention it here:

Scheme Variable: make-program objcode objtable [free-vars=#f]
C Function: scm_make_program (objcode, objtable, free_vars)

Load up object code into a Scheme program. The resulting program will have objtable as its object table, which should be a vector or #f, and will capture the free variables from free-vars.

Object code from a file may be disassembled at the REPL via the meta-command ,disassemble-file, abbreviated as ,xx. Programs may be disassembled via ,disassemble, abbreviated as ,x.

Compiling object code to the fake language, value, is performed via loading objcode into a program, then executing that thunk with respect to the compilation environment. Normally the environment propagates through the compiler transparently, but users may specify the compilation environment manually as well, as a module.
