Changes between Version 6 and Version 7 of InternalsMiscellany


Ignore:
Timestamp:
05/11/09 08:12:38 (6 years ago)
Author:
lpolzer
Comment:

Moved the larger part of this page to separate pages in the internals section.

Legend:

Unmodified
Added
Removed
Modified
  • InternalsMiscellany

    v6 v7  
    1 [[TOC]] 
    2 = Assorted internals tidbits = 
    3  
    4 == Compiler backend == 
    5 {{{ 
    6 VINSN   Virtual instruction (probably akin to SBCL's VOPs) 
    7   LAP   Lisp Assembly Parser; compiles SEXPs into opcodes 
    8 }}} 
    9  
    10 === VINSN macros === 
    11 {{{ 
    12 <-    copy register 
    13 @     label 
    14 @=    label (aligned) 
    15 ->    jump to label 
    16 ^     branch 
    17 ?     register (unwired) 
    18 $     register (wired) 
    19 }}} 
    20  
    21 (from compiler/X86/x862.lisp) 
    22  
    23 === Operand syntax === 
    24 {{{ 
    25 (% x)    register 
    26 ($ x)    immediate 
    27 (@ x)    memory operand; x ~ ([seg] [disp] [base] [index] [scale]) 
    28 x        labelref 
    29 (:rcontext x)   memory operand, using segment register or gpr; see @ for syntax of x. 
    30 (:self fn)      self-reference 
    31 }}} 
    32  
    33 (from compiler/X86/x86-lap.lisp) 
     1This page contains snippets of internals information that are work in progress. 
    342 
    353== Kernel == 
    364  * x86: the FS register contains a pointer to the current TCR. 
    375  * x86: the TCR is defined in lisp-kernel/x86-constants32.h (struct tcr) 
    38  
    39 === Memory allocation === 
    40 Explanation by gb: 
    41  
    42   Memory allocation is per-thread; a thread conses within a private "chunk" of memory by decrementing a per-thread pointer that starts at the high end of its current chunk and comparing that pointer to the low end of the chunk; if the pointer's above the limit, we use the memory, otherwise we need a new chunk: 
    43  
    44 {{{ 
    45    [21]    (subl ($ 7) (@ (% fs) 132))  ; subtract the size of a cons - the tag of a 
    46 cons 
    47                                         ; from the per-thread pointer 
    48    [30]    (movl (@ (% fs) 132) (% temp0)) ; load the per-thread pointer into a temp 
    49 reg 
    50    [38]    (cmpl (@ (% fs) 136) (% temp0)) ; compare to limit 
    51    [46]    (ja L50)                        ; continue if above limit 
    52    [48]    (uuo-alloc)                     ; trap, get a new chunk 
    53 L50 
    54    [50]    (andb ($ 248) (@ (% fs) 132))   ; clear tag bits in thread-local storage 
    55    [59]    (movl (% arg_y) (@ 3 (% temp0))) ; store car 
    56    [62]    (movl (% arg_z) (@ -1 (% temp0))) ; store cdr 
    57    [65]    (movl (% temp0) (% arg_z))      ; return cons cell 
    58 }}} 
    59  
    60 == Exception handling == 
    61 The manual has some information on this. Here's some more. 
    62  
    63 === UUOs (by gb) === 
    64  
    65 ==== Origin ==== 
    66 On the DEC PDP-10, the acronym UUO stood for "Unimplemented User Operation"; UUOs were used to invoke system services and/or to invoke what we'd think of as exception handlers. [...] As it's used in CCL, the term just means "an illegal instruction that'll ultimately cause a lisp-aware handler function to be called." 
    67  
    68 ==== Implementation details ==== 
    69 Executing an "int $n" (#xcd n) instruction transfers control to an 
    70 entry insome (incredibly complex and baroque) table of handlers 
    71 maintained by the chip.  The OS might use a few entries in this table 
    72 to implement system calls (though modern x86 CPUs often have faster 
    73 ways of doing system calls), and some entries are reserved for hardware- 
    74 related interrupts. 
    75  
    76 Trying to execute an "int $n" instruction that doesn't have a defined 
    77 entry in this table causes a General Protection Fault, and this 
    78 eventually causes (on Unix) a signal to be raised.  Exactly what 
    79 signal depends on the OS; there's a macro called SIGNUM_FOR_INTN_TRAP 
    80 defined conditionally in ccl/lisp-kernel/x86-exceptions.h that defines 
    81 this.  As you can see, it's generally overloaded on SIGBUS or SIGSEGV, 
    82 which usually indicates an addressing exception (yes, SIGILL would 
    83 make more sense, but since it involves a GP fault an undefined "int 
    84 $n" winds up taking the same path as a memory protection fault) and 
    85 we need to look at other arguments to the signal handler (as defined 
    86 by the IS_MAYBE_INT_TRAP macro: if IS_MAYBE_INT_TRAP is true, we believe 
    87 that we can look at the the byte that the PC in the signal context is 
    88 pointing to to see if it's #xcd; if not, the SIGSEGV or SIGBUS might 
    89 have been caused by trying to execute code at an unmapped address.) 
    90  
    91 We also use "ud2a" instructions (followed by a byte or more of data) 
    92 for similar purposes, but "int $n" is generally shorter; illegal 
    93 instructions that use the ud2a opcode (which generally -does- raise 
    94 SIGILL when executed) are sometimes called "xuuos" (eXtended UUOs). 
    95  
    96 Once in a while (when doing a port to a new OS), we've found that the 
    97 OS uses an interrupt that we've previously considered free for our 
    98 use, and have had to do things differently (reassign UUOs or avoid 
    99 emitting conflicting ones.)  I suppose that that could happen if we 
    100 ported to some other OS (NetBSD ?), but it's unlikely that x8632 OSes 
    101 will invoke new functionality via "int $n" (since other means of doing 
    102 system calls are generally faster/better.)  See the comment in x86-asm.lisp: 
    103  
    104 ;;; DON'T use #xcd8x: doing so will make Mach angry and confused.