123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162 |
- #####
- #
- # TAGGING
- #
- We're working on a machine with 64 bit words that address bytes.
- * 64 bits = 2^3 = 8 bytes
- If we ensure our pointers are 8 byte aligned then their
- addresses all end in 000. We can use these 3 bits as a tag.
- pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppttt
- not every object is a pointer though, we have immediates:
- (A) bool, nil, symbol, char
- (B) number
- (We don't need the symbol object to be a pointer, an index into the
- symbol table is fine since displaying symbol names isn't a speed
- priority.)
- In the case of immediates we can smush several into one ttt tag
- and use some more bits ss to distinguish them:
- iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiissttt
- We also make vectors a special type of a record, to save a tag.
- * The special 'all zeros' value of #f can be used with jnz.
- * We can save the 'nil' value in a register for fast comparison.
- * Char is large enough to hold a unicode code point.
- type obj data
- --------------------------------------
- bool #f .....0[00][000]
- bool #t .....1[00][000]
- nil nil .....0[01][000]
- symbol [--32 bits--]...[10][000]
- char [--32 bits--]...[11][000]
- number [-------61 bits------][001]
- cons *[010]
- closure *[011]
- string *[100]
- vector + record *[101]
- io port [110]
- gc-redirect marker *[111]
- #####
- #
- # LAYOUT
- #
- All objects will point into the heap except strings may be stored
- elsewhere (e.g. constant strings stored in the data section).
- ptr heap
- -------------------------------------------------------------
- cons --> [ car ][ cdr ]
- closure --> [ label ][ length ][ env1 ][ env2 ]...
- string --> <string-data>
- vec/rec --> [ tag/len ][ field-1 ][ field 2 ][ field-3 ]...
- gc-mark --> <an objects new place in the other-heap>
- #####
- #
- # CALLING CONVENTION
- #
- The calling convention is like this:
- - Caller enter:
- push return-address
- push base-pointer
- push arg-1
- push arg-2
- ...
- push arg-n
- set base-pointer to stack-pointer
- jump func
- this sets the stack up like:
- [ret addr][saved bp][arg-1][arg-2]..[arg-n]
- ^ new bp
- - Callee enter:
- increase the stack size to make space for its own temps
- - Callee exit:
- we need to throw away all the temps and args. can do this in one step.
- then restore the previous base pointer
- and ret
- mov rsp, rbp
- pop rbp
- ret
- - Caller exit:
- The caller has no resposibility.
- All the args it pushed on the stack have been consumed, base pointer restored.
- #####
- #
- # STACK
- #
- The stack layout needs to support the following:
- * The garbage collector needs to scan through to as a gc root.
- For this to be possible it has to be able to skip past non scheme objects like labels.
- * We need to be able to produce stack traces based on the labels.
- * Support variable number of arguments to function calls
- . previous stack .
- : frame :
- +----------------+
- | return address |
- +----------------+
- | saved base ptr |
- +----------------+
- | arg 1 | <- base pointer
- +----------------+
- | arg 2 |
- +----------------+
- : :
- : :
- +----------------+
- | arg n |
- +----------------+
- | tmp 1 |
- +----------------+
- | tmp 2 |
- +----------------+
- : :
- : :
- +----------------+
- | tmp n |
- +----------------+
- : scheme objects : (this will usually just
- : saved by the : be the env register)
- : callee :
- +----------------+
- . <-- stack pointer
- args will be referenced relative to base pointer
- temporaries will be referenced relative to stack pointer
- this allows us to support variadic functions!
- in the case of a variadic function the callee must cons up the rest list. The reason for this is it allows fast function calls in the non-variadic case.
|