Skip to content

Runtime System Linkage

John Reppy edited this page Dec 10, 2023 · 1 revision

Linkage Between the Runtime System and SML Code

Overview

This document describes the mechanisms that provide the linkage between the SML/NJ Runtime system and executing code. These mechanisms are quite crufty and inflexible with many vistigial features, so we describe a new design at the end that is both more flexible and that removes the cruft.

The Assembly structure

The Assembly structure is a pseudo-structure whose actual implementation is in the runtime system. It provides access to a small collection of assembly routines (these use SML calling conventions) as well as to values that both the runtime and SML code must access. It has the following signature:

signature ASSEMBLY =
  sig
    type object
    datatype 'a option = NONE | SOME of 'a

    structure A :
      sig
        type c_function
        type word8array = PrimTypes.word8array
        eqtype real64array
        type spin_lock

        val array : int * 'a -> 'a array
        val bind_cfun : (string * string) -> c_function
        val callc : (c_function * 'a) -> 'c
        val create_b : int -> word8array
        val create_r : int -> real64array
        val create_s : int -> string
        val create_v : int * 'a list -> 'a vector
        val floor : real -> int
        val logb : real -> int
        val scalb : real * int -> real
        val try_lock : spin_lock -> bool
        val unlock : spin_lock -> unit
      end

    exception Div
    exception Overflow
    exception SysErr of (string * int option)

    val profCurrent : int ref
    val pollEvent : bool ref
    val pollFreq : int ref
    val pollHandler : (unit cont -> unit cont) ref
    val activeProcs : int ref
    val pstruct : object ref
    val sighandler : ((int * int * unit cont) -> unit cont) ref
    val vector0 : 'a vector
  end
  • The Assembly structure has a predictable layout — essentially a record of the exception and value identifiers in the order in which they appear (i.e., the type component are erased).

  • Note that this module is where the Div, Overflow, and SysErr exceptions are defined.

  • Because the binding to the Assembly structure is static, it is only possible for the compiler to access its components during the early phases where the static environment is present.

  • The module has a number of fields that are no longer used.

    • The Div exception was included to allow the runtime system to map division-by-zero traps to raising the exception, but we no longer use this mechanism. Instead, we explicitly test for zero before doing the divide. The Div exception could be moved to the Core structure.

    • The software polling mechanisms are no longer supported, so the pollEvent, pollFreq, pollHandler fields could be eliminated.

    • The multiprocessor support is no longer supported, so the activeProcs field is not needed; also the try_lock and unlock functions can be removed from the A substructure.

    • The logb function has been deprecated, so we can remove it from the A substructure.

The Assembly Glue Code

The Assembly.A structure is implemented in target-specific assembly code. In addition, there is assembly code that is used to handle the transfer of control between the runtime system and SML code. The assembly code implements the following functions:

sigh_return_a

This code is an entrypoint to the runtime system (request code REQ_SIG_RETURN) that is used as the return continuation when invoking a SML signal handler.

sigh_resume

This code is an entrypoint to the runtime system (request code REQ_SIG_RESUME) that is used as the continuation argument to a SML signal handler.

pollh_return_a

This code is an entrypoint to the runtime system (request code REQ_POLL_RETURN) that is used as the return continuation when invoking a SML software-polling handler.
Note that software polling is no longer supported.

pollh_resume

This code is an entrypoint to the runtime system (request code REQ_POLL_RESUME) that is used as the continuation argument to a SML software-polling handler.
Note that software polling is no longer supported.

handle_a

This code is an entrypoint to the runtime system (request code REQ_EXN) that is used as the exception handler of last resort (i.e., the initial value of the exception-handler CMachine reguister.

return_a

This code is an entrypoint to the runtime system (request code REQ_RETURN) that

request_fault

This code is an entrypoint to the runtime system (request code REQ_FAULT) that

bind_cfun

This code is an entrypoint to the runtime system (request code REQ_BIND_CFUN) that is used to get the address of a runtime-system function.

build_literals

This code is an entrypoint to the runtime system (request code REQ_BUILD_LITERALS) that is used to build the record of literal values for a compilation unit.

callc_a

This code is an entrypoint to the runtime system (request code REQ_CALLC) that is used to call a runtime-system function that was returned by bind_cfun.

saveregs

This code is an entrypoint to the runtime system (request code REQ_GC) that is used to invoke the garbage collector.

set_request

This code is the common code that handles the transfer of control from SML to the runtime system. It is used by all of the runtime-system entrypoints listed above.

restoreregs

This function is used to transfer control from the runtime system to SML code. It allocates and initialized the SML stack frame and CMachine registers, and then invokes the SML code.

array_a

This code is the implementation of the `Assembly.A.array function, which allocates a polymorphic array initialized to a given value.

create_b_a

This code is the implementation of the `Assembly.A.create_b function, which allocates an uninitialized monomorphic array of 8-bit elements.

create_r_a

This code is the implementation of the `Assembly.A.create_r function, which allocates an uninitialized monomorphic array of 64-bit reals.

create_s_a

This code is the implementation of the `Assembly.A.create_b function, which allocates an uninitialized monomorphic vector of 8-bit elements (aka, a string).

create_v_a

This code is the implementation of the `Assembly.A.create_v function, which creates a polymorphic vector from a list of values.

floor_a

This code is the implementation of the `Assembly.A.floor function, which computes the integer floor of a boxed real.

logb_a

This code is the implementation of the Assembly.A.logb function, which extracts the unbiased exponent from a boxed real value.
Note: the `logb
function is no longer used and is considered deprecated.

scalb_a

This code is the implementation of the `Assembly.A.scalb function, which multiplies a real by a power of two.

try_lock_a

This code is the implementation of the Assembly.A.try_lock function, which acquires a spin lock.
Note that this function is not used for anything anymore and is not implemented on many targets.

unlock_a

This code is the implementation of the Assembly.A.unlock function, which releases a spin lock.
Note that this function is not used for anything anymore and is not implemented on many targets.

A Proposal for the Future

  • remove unused components (A.logb, A.try_lock, and A.unlock).

  • Generalize the creation functions to support more kinds of arrays and vectors in the future. This might involve splitting the creation of the data area from creating the header.

  • Make Overflow exception (and possibly others) dynamically accessible. We can do this by adding them to the stack at known locations.

Clone this wiki locally