mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-08-05 13:26:55 +00:00
With this patch, the LowerGC transformation becomes the
ShadowStackCollector, which additionally has reduced overhead with no sacrifice in portability. Considering a function @fun with 8 loop-local roots, ShadowStackCollector introduces the following overhead (x86): ; shadowstack prologue movl L_llvm_gc_root_chain$non_lazy_ptr, %eax movl (%eax), %ecx movl $___gc_fun, 20(%esp) movl $0, 24(%esp) movl $0, 28(%esp) movl $0, 32(%esp) movl $0, 36(%esp) movl $0, 40(%esp) movl $0, 44(%esp) movl $0, 48(%esp) movl $0, 52(%esp) movl %ecx, 16(%esp) leal 16(%esp), %ecx movl %ecx, (%eax) ; shadowstack loop overhead (none) ; shadowstack epilogue movl 48(%esp), %edx movl %edx, (%ecx) ; shadowstack metadata .align 3 ___gc_fun: # __gc_fun .long 8 .space 4 In comparison to LowerGC: ; lowergc prologue movl L_llvm_gc_root_chain$non_lazy_ptr, %eax movl (%eax), %ecx movl %ecx, 48(%esp) movl $8, 52(%esp) movl $0, 60(%esp) movl $0, 56(%esp) movl $0, 68(%esp) movl $0, 64(%esp) movl $0, 76(%esp) movl $0, 72(%esp) movl $0, 84(%esp) movl $0, 80(%esp) movl $0, 92(%esp) movl $0, 88(%esp) movl $0, 100(%esp) movl $0, 96(%esp) movl $0, 108(%esp) movl $0, 104(%esp) movl $0, 116(%esp) movl $0, 112(%esp) ; lowergc loop overhead leal 44(%esp), %eax movl %eax, 56(%esp) leal 40(%esp), %eax movl %eax, 64(%esp) leal 36(%esp), %eax movl %eax, 72(%esp) leal 32(%esp), %eax movl %eax, 80(%esp) leal 28(%esp), %eax movl %eax, 88(%esp) leal 24(%esp), %eax movl %eax, 96(%esp) leal 20(%esp), %eax movl %eax, 104(%esp) leal 16(%esp), %eax movl %eax, 112(%esp) ; lowergc epilogue movl 48(%esp), %edx movl %edx, (%ecx) ; lowergc metadata (none) git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@45670 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -97,24 +97,26 @@ void llvm_gc_write(void *V, void *ObjPtr, void **FieldPtr) { *FieldPtr = V; }
|
||||
* FIXME: This should be in a code-generator specific library, but for now this
|
||||
* will work for all code generators.
|
||||
*/
|
||||
typedef struct GCRoot {
|
||||
void **RootPtr;
|
||||
void *Meta;
|
||||
} GCRoot;
|
||||
struct FrameMap {
|
||||
int32_t NumRoots; // Number of roots in stack frame.
|
||||
int32_t NumMeta; // Number of metadata descriptors. May be < NumRoots.
|
||||
void *Meta[]; // May be absent for roots without metadata.
|
||||
};
|
||||
|
||||
typedef struct GCRoots {
|
||||
struct GCRoots *Next;
|
||||
unsigned NumRoots;
|
||||
GCRoot RootRecords[];
|
||||
} GCRoots;
|
||||
GCRoots *llvm_gc_root_chain;
|
||||
struct StackEntry {
|
||||
ShadowStackEntry *Next; // Caller's stack entry.
|
||||
const FrameMap *Map; // Pointer to constant FrameMap.
|
||||
void *Roots[]; // Stack roots (in-place array).
|
||||
};
|
||||
StackEntry *llvm_gc_root_chain;
|
||||
|
||||
void llvm_cg_walk_gcroots(void (*FP)(void **Root, void *Meta)) {
|
||||
GCRoots *R = llvm_gc_root_chain;
|
||||
for (; R; R = R->Next) {
|
||||
for (StackEntry *R; R; R = R->Next) {
|
||||
unsigned i, e;
|
||||
for (i = 0, e = R->NumRoots; i != e; ++i)
|
||||
FP(R->RootRecords[i].RootPtr, R->RootRecords[i].Meta);
|
||||
for (i = 0, e = R->NumMeta; i != e; ++i)
|
||||
FP(&R->Roots[i], R->Map->Meta[i]);
|
||||
for (e = R->NumRoots; i != e; ++i)
|
||||
FP(&R->Roots[i], NULL);
|
||||
}
|
||||
}
|
||||
/* END FIXME! */
|
||||
|
Reference in New Issue
Block a user