1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
|
#pragma once
namespace storm {
/**
* Describes a reference inside the generated code.
*
* The actual pointers for the references are stored inside the 'GcCodeRef' itself. These are
* the pointers that are actually scanned by the garbage collector, but the garbage collector
* will make sure to keep the described reference updated as well. Call
* 'runtime::codeUpdatePtrs' when all references have been filled in to update the references
* which 'offset' denotes.
*
* In the case of 'inside' references, the value stored in the 'pointer' member is a value to be
* interpreted as the offset within the current object, rather than an actual pointer.
*
* Note: If the LSB of the kind is set, the 'pointer' for that entry is scanned by the GC. To
* simplify, we use the entire least significant hex digit to indicate if the entry is scanned
* or not. The rest of the numbers are increasing as the enum would do normally.
*/
struct GcCodeRef {
// Kind of reference. Ie. how do we read or write this reference to/from memory?
enum Kind {
// Disabled for now.
disabled = 0x00,
// Diabled, but scanned. I.e., we store some information inside 'pointer', but the value
// of 'pointer' is not written anywhere in the code.
ptrStorage = 0x01,
// Raw pointer. Reads 4/8 bytes from 'offset' and treats those as a pointer.
rawPtr = 0x11,
// Offset pointer to a GC:d object. Reads 4/8 bytes from 'offset' and treats those as a
// pointer relative (offset + sizeof(size_t)), ie. the address just after the pointer.
relativePtr = 0x21,
// A relative non-gc pointer to somewhere. This is updated as the object moves, but is
// never scanned.
relative = 0x30,
// An absolute pointer to somewhere within this code section. This is updated whenever
// the object moves, but is never scanned as it does not point to the start of an object.
inside = 0x40,
// Marker for a back-edge. The 'pointer' field contains an offset into this code listing
// to indicate where the back edge leads to.
backEdge = 0x50,
// A relative (4-byte) pointer to one of the 'pointer' variables in the GcCodeRef
// itself. The value stored inside 'pointer' must be an actual pointer, since it is
// scanned by the GC. It can not be used to conveniently store large numbers etc.
relativeHere = 0x61,
// An architecture specific pointer that modifies the jump instruction as well, so that
// we can properly support both long and short jump instructions (if wee need to
// distinguish them) in an efficient manner by using short jumps where possible and
// falling back to long jumps where necessary.
jump = 0x71,
// Update an entry in CodeTable, for unwinding information. 'pointer' is a pointer to
// the location that shall be updated.
codeInfo = 0x80,
// Update an entry in DwarfTable, for unwinding information. 'pointer' is a pointer to
// the location that shall be updated.
dwarfInfo = 0x90,
// ARM-specific version of "relativeHere". Writes an offset to the "pointer" member in
// this struct at the offset indicated in 'offset'. This offset must be aligned to 4
// bytes. This option assumes that it updates a 19-bit immediate located at bits 5..23.
relativeHereImm19 = 0xA1,
// ...
};
// Offset inside the code where this reference is located. Does not need to be aligned, that
// depends entirely on the underlying machine we're working with.
nat offset;
// Reference type.
Kind kind;
// The pointer to be scanned. In the case where 'kind == inside', stores an offset into this
// object instead.
void *pointer;
};
/**
* Describes allocated code.
*
* NOTE: It is _not_ possible to store pointers to GcCode objects anywhere except for the stack,
* as these are really pointers into an object.
*
* TODO: Expose to Storm? This is only needed when writing the lowest parts of code-generating
* backends, which is only really neccessary when porting Storm to a new platform, so this has a
* very low priority.
*/
struct GcCode {
// Number of entries. Only changed on allocation.
const size_t refCount;
// Reserved for internal use by the GC. Do not alter.
void *reserved;
// References in here.
GcCodeRef refs[1];
};
}
|