From 17e0374d393ce446fd1ec5aac38da1ff31d2ac7e Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Sat, 29 Dec 2018 01:11:00 +0000 Subject: [PATCH] Use CALL/RET for pushing and returning to continuations on amd64. Calls now look like: ;; (assign (register #x123) (cons-pointer tag (entry:continuation cont))) (CALL (@PCR pushed)) (JMP (@PCR cont)) pushed: (OR Q (@R ,rsp) (&U ,tag)) ... (JMP (@PCR uuo-link)) Returns now look like: ;; (pop-return) (AND Q (@R ,rsp) (R ,regnum:datum-mask)) (RET) These should happen in pairs, so that we can take advantage of the CPU's return address branch target prediction stack rather than abusing the indirect jump branch target predictor. WARNING: This changes the amd64 compiled code interface, so new compiled code requires a new microcode. (A new microcode might be able to handle existing compiled code just fine.) --- src/compiler/machines/x86-64/rules1.scm | 31 ++++++++++++++++++++++--- src/compiler/machines/x86-64/rules3.scm | 10 ++++---- src/microcode/cmpintmd/x86-64.c | 11 +++++++++ src/microcode/cmpintmd/x86-64.h | 4 +++- 4 files changed, 46 insertions(+), 10 deletions(-) diff --git a/src/compiler/machines/x86-64/rules1.scm b/src/compiler/machines/x86-64/rules1.scm index a327bcb15..5f6acf4d0 100644 --- a/src/compiler/machines/x86-64/rules1.scm +++ b/src/compiler/machines/x86-64/rules1.scm @@ -175,7 +175,12 @@ USA. (define-rule statement (ASSIGN (REGISTER (? target)) (ENTRY:CONTINUATION (? label))) - (load-pc-relative-address (target-register-reference target) label 8)) + (let* ((target (target-register-reference target)) + (get-pc (generate-label 'GET-PC))) + (LAP (CALL (@PCR ,get-pc)) + (JMP (@PCRO ,label 8)) + (LABEL ,get-pc) + (POP Q ,target)))) (define-rule statement ;; This is an intermediate rule -- not intended to produce code. @@ -195,8 +200,28 @@ USA. (CONS-POINTER (MACHINE-CONSTANT (? type)) (ENTRY:CONTINUATION (? label)))) (assert (= type type-code:compiled-return)) - (load-pc-relative-address/typed (target-register-reference target) - type label 8)) + (let* ((target (target-register-reference target)) + (temp (temporary-register-reference)) + (pushed (generate-label 'PUSHED))) + (LAP (CALL (@PCR ,pushed)) + (JMP (@PCRO ,label 8)) + (LABEL ,pushed) + (POP Q ,target) + (MOV Q ,temp (&U ,(make-non-pointer-literal type 0))) + (OR Q ,target ,temp)))) + +(define-rule statement + (ASSIGN (PRE-INCREMENT (REGISTER 4) -1) + (CONS-POINTER (MACHINE-CONSTANT (? type)) + (ENTRY:CONTINUATION (? label)))) + (assert (= type type-code:compiled-return)) + (let* ((temp (temporary-register-reference)) + (pushed (generate-label 'PUSHED))) + (LAP (CALL (@PCR ,pushed)) + (JMP (@PCRO ,label 8)) + (LABEL ,pushed) + (MOV Q ,temp (&U ,(make-non-pointer-literal type 0))) + (OR Q (@R 4) ,temp)))) (define-rule statement (ASSIGN (REGISTER (? target)) (VARIABLE-CACHE (? name))) diff --git a/src/compiler/machines/x86-64/rules3.scm b/src/compiler/machines/x86-64/rules3.scm index 8f49c4707..74c747be8 100644 --- a/src/compiler/machines/x86-64/rules3.scm +++ b/src/compiler/machines/x86-64/rules3.scm @@ -39,9 +39,8 @@ USA. (cond ((null? checks) (current-bblock-continue! (make-new-sblock - (LAP (POP Q (R ,rax)) ; continuation - (AND Q (R ,rax) (R ,regnum:datum-mask)) ; clear type - (JMP (R ,rax)))))) + (LAP (AND Q (@R ,rsp) (R ,regnum:datum-mask)) + (RET))))) ((block-association 'POP-RETURN) => current-bblock-continue!) (else @@ -50,9 +49,8 @@ USA. (let ((interrupt-label (generate-label 'INTERRUPT))) (LAP (CMP Q (R ,regnum:free-pointer) ,reg:compiled-memtop) (JGE (@PCR ,interrupt-label)) - (POP Q (R ,rax)) ; continuation - (AND Q (R ,rax) (R ,regnum:datum-mask)) ; clear type - (JMP (R ,rax)) + (AND Q (@R ,rsp) (R ,regnum:datum-mask)) + (RET) (LABEL ,interrupt-label) ,@(invoke-hook entry:compiler-interrupt-continuation-2)))))) diff --git a/src/microcode/cmpintmd/x86-64.c b/src/microcode/cmpintmd/x86-64.c index be21835ae..19e168e3b 100644 --- a/src/microcode/cmpintmd/x86-64.c +++ b/src/microcode/cmpintmd/x86-64.c @@ -63,6 +63,17 @@ write_cc_entry_offset (cc_entry_offset_t * ceo, insn_t * address) = (((ceo->offset) << 1) | ((ceo->continued_p) ? 1 : 0)); return (false); } + +insn_t * +cc_return_address_to_entry_address (insn_t * pc) +{ + if ((pc[0]) == 0xeb) /* JMP rel8 */ + return ((pc + 2) + (* ((int8_t *) &pc[1])) - 8); + else if ((pc[0]) == 0xe9) /* JMP rel32 */ + return ((pc + 5) + (* ((int32_t *) &pc[1])) - 8); + else + return (pc - 8); +} /* Compiled closures */ diff --git a/src/microcode/cmpintmd/x86-64.h b/src/microcode/cmpintmd/x86-64.h index d48aee366..4acce5472 100644 --- a/src/microcode/cmpintmd/x86-64.h +++ b/src/microcode/cmpintmd/x86-64.h @@ -161,7 +161,9 @@ typedef uint8_t insn_t; #define CC_RETURN_ADDRESS_PTR(r) 0 #define CC_RETURN_ADDRESS_PC(r) (r) -#define CC_RETURN_ADDRESS_TO_ENTRY_ADDRESS(r) (((insn_t *) (r)) - 8) +insn_t * cc_return_address_to_entry_address (insn_t *); + +#define CC_RETURN_ADDRESS_TO_ENTRY_ADDRESS cc_return_address_to_entry_address #define EMBEDDED_CLOSURE_ADDRS_P 1 -- 2.25.1