Simplify hook calls.
authorTaylor R Campbell <campbell@mumble.net>
Sat, 29 Dec 2018 16:40:02 +0000 (16:40 +0000)
committerTaylor R Campbell <campbell@mumble.net>
Tue, 13 Aug 2019 14:37:02 +0000 (14:37 +0000)
No need for CALL or the stack to be involved: just load PC-relative
address into RBX directly.  Should shave off a few bytes of code.

WARNING: This changes the amd64 compiled code interface so that new
compiled code requires a new microcode and vice versa.

src/compiler/machines/x86-64/lapgen.scm
src/compiler/machines/x86-64/rules3.scm
src/compiler/machines/x86-64/rules4.scm
src/compiler/machines/x86-64/rulfix.scm
src/microcode/cmpauxmd/x86-64.m4

index 653721a87d96b1448fe0c038ad7d0331e2e770aa..df1e76c6f52a6b475b9ae501510c5cea050ca13e 100644 (file)
@@ -712,19 +712,20 @@ USA.
 (define-integrable (invoke-hook entry)
   (LAP (JMP ,entry)))
 
-(define (invoke-hook/call entry)
-  (let* ((get-pc (generate-label 'GET-PC))
-        (hook-context (generate-label 'HOOK-CONTEXT)))
-    (LAP (CALL (@PCR ,get-pc))
-       (LABEL ,get-pc)
-        ;; ADD r/m64,imm8              48 83 04 24 xx
-        ;; JMP r/m64                   ff 86 yy yy yy yy
-        ;; Register displacement for JMP is always >=0x80, so can't
-        ;; fit in signed byte and thus must use 32-bit displacement.
-        ;; Hence xx = 0x0b = 11.
-        (ADD Q (@R ,rsp) (& #x0b))
-        (JMP ,entry)
-       (LABEL ,hook-context))))
+;; Invoke a hook that will pop an untagged return address off the stack
+;; and jump to it with RET, just like a C subroutine.
+
+(define-integrable (invoke-hook/subroutine entry)
+  (LAP (CALL ,entry)))
+
+;; Invoke a hook that expects a compiled entry address in rbx and will
+;; jump to it with JMP.
+
+(define (invoke-hook/reentry entry)
+  (let ((label (generate-label 'HOOK-REENTRY)))
+    (LAP (LEA Q (R ,rbx) (@PCRO ,label 4)) ;Skip format word.
+        ,@(invoke-hook entry)
+        (LABEL ,label))))
 
 (define-integrable (invoke-interface code)
   (LAP (MOV B (R ,r9) (& ,code))
@@ -732,7 +733,7 @@ USA.
 
 (define-integrable (invoke-interface/call code)
   (LAP (MOV B (R ,r9) (& ,code))
-       ,@(invoke-hook/call entry:compiler-scheme-to-interface/call)))
+       ,@(invoke-hook/reentry entry:compiler-scheme-to-interface/call)))
 \f
 (define-syntax define-entries
   (sc-macro-transformer
index 150900e233759a3aa957c1557bdd2248c182c8c0..787efe41c696c84d690b011e83abbd6be14e836d 100644 (file)
@@ -99,17 +99,17 @@ USA.
         ,@(invoke-hook entry:compiler-shortcircuit-apply)
         |#
         ,@(case frame-size
-            ((1) (LAP (CALL ,entry:compiler-apply-setup-size-1)))
-            ((2) (LAP (CALL ,entry:compiler-apply-setup-size-2)))
-            ((3) (LAP (CALL ,entry:compiler-apply-setup-size-3)))
-            ((4) (LAP (CALL ,entry:compiler-apply-setup-size-4)))
-            ((5) (LAP (CALL ,entry:compiler-apply-setup-size-5)))
-            ((6) (LAP (CALL ,entry:compiler-apply-setup-size-6)))
-            ((7) (LAP (CALL ,entry:compiler-apply-setup-size-7)))
-            ((8) (LAP (CALL ,entry:compiler-apply-setup-size-8)))
+            ((1) (invoke-hook/subroutine entry:compiler-apply-setup-size-1))
+            ((2) (invoke-hook/subroutine entry:compiler-apply-setup-size-2))
+            ((3) (invoke-hook/subroutine entry:compiler-apply-setup-size-3))
+            ((4) (invoke-hook/subroutine entry:compiler-apply-setup-size-4))
+            ((5) (invoke-hook/subroutine entry:compiler-apply-setup-size-5))
+            ((6) (invoke-hook/subroutine entry:compiler-apply-setup-size-6))
+            ((7) (invoke-hook/subroutine entry:compiler-apply-setup-size-7))
+            ((8) (invoke-hook/subroutine entry:compiler-apply-setup-size-8))
             (else
              (LAP (MOV Q (R ,rdx) (&U ,frame-size))
-                  (CALL ,entry:compiler-apply-setup))))
+                  ,@(invoke-hook/subroutine entry:compiler-apply-setup))))
         (JNE (@PCR ,generic))
         (JMP (R ,rax))
        (LABEL ,generic)
@@ -444,7 +444,7 @@ USA.
        (LAP ,@(make-external-label code-word label))
        (let ((gc-label (generate-label)))
          (LAP (LABEL ,gc-label)
-              ,@(invoke-hook/call entry)
+              ,@(invoke-hook/reentry entry)
               ,@(make-external-label code-word label)
               ,@(interrupt-check gc-label checks))))))
 
@@ -457,6 +457,10 @@ USA.
 (define-rule statement
   (CONTINUATION-HEADER (? internal-label))
   #|
+  ;; Note: This is wrong -- compiler-interrupt-continuation expects a
+  ;; compiled return address on the stack, but this will yield compiled
+  ;; entry addresses.  If you uncomment this, prepare to deal with the
+  ;; consequences.
   (simple-procedure-header (continuation-code-word internal-label)
                           internal-label
                           entry:compiler-interrupt-continuation)
@@ -679,7 +683,7 @@ USA.
        #|
        ,@(invoke-interface/call code:compiler-link)
        |#
-       ,@(invoke-hook/call entry:compiler-link)
+       ,@(invoke-hook/reentry entry:compiler-link)
        ,@(make-external-label (continuation-code-word #f)
                              (generate-label))))
 
@@ -696,7 +700,7 @@ USA.
        #|
        ,@(invoke-interface/call code:compiler-link)
        |#
-       ,@(invoke-hook/call entry:compiler-link)
+       ,@(invoke-hook/reentry entry:compiler-link)
        ,@(make-external-label (continuation-code-word #f)
                              (generate-label))))
 \f
@@ -745,7 +749,7 @@ USA.
              (@ROI ,rdx ,(* 2 address-units-per-object)
                    ,rax ,address-units-per-object))
         ;; Invoke linker
-        ,@(invoke-hook/call entry:compiler-link)
+        ,@(invoke-hook/reentry entry:compiler-link)
         ,@(make-external-label (continuation-code-word false)
                                (generate-label))
         ;; Increment counter and loop
index 3c20a034b76a1811445f07fc7fde1bce4bd6a0dc..61a361b471d8bc40370478223664923b051d1d06 100644 (file)
@@ -45,9 +45,10 @@ USA.
                code:compiler-safe-reference-trap
                code:compiler-reference-trap))
         |#
-        ,@(invoke-hook/call (if safe?
-                                entry:compiler-safe-reference-trap
-                                entry:compiler-reference-trap)))))
+        ,@(invoke-hook/reentry
+           (if safe?
+               entry:compiler-safe-reference-trap
+               entry:compiler-reference-trap)))))
 
 (define-rule statement
   (INTERPRETER-CALL:CACHE-ASSIGNMENT (? cont) (? extension) (? value))
@@ -63,7 +64,7 @@ USA.
         #|
         ,@(invoke-interface/call code:compiler-assignment-trap)
         |#
-        ,@(invoke-hook/call entry:compiler-assignment-trap))))
+        ,@(invoke-hook/reentry entry:compiler-assignment-trap))))
 
 (define-rule statement
   (INTERPRETER-CALL:CACHE-UNASSIGNED? (? cont) (? extension))
index 0eb80343685dfb97d7f986351a8f72b570598df7..9a0a9ad98d5ad9c5f523d730437d7991cab70a12 100644 (file)
@@ -473,7 +473,7 @@ USA.
           ;; Clearing the map is not necessary because the hook uses
           ;; only rax and rcx.  If the hook were changed, it would be
           ;; necessary to clear the map first.
-          ,@(invoke-hook/call entry:compiler-fixnum-shift)))))
+          ,@(invoke-hook/subroutine entry:compiler-fixnum-shift)))))
 \f
 (define (do-division target source1 source2 result-reg)
   (prefix-instructions! (load-machine-register! source1 rax))
index 27e8ed1c9737a51813be83a471ed967171f302d0..f98d8426c0a8d7ef22d1bf448c05173cbd01f45e 100644 (file)
@@ -426,10 +426,13 @@ define_debugging_label(trampoline_to_interface)
        OP(mov,q)       TW(REG(rcx),REG(rbx))           # argument in rbx
        jmp     scheme_to_interface
 
+# We used to CALL this to get the return address on the stack, but now
+# we use RIP-relative addressing to load directly into %rbx -- which
+# doesn't ruin the return address branch target prediction stack -- so
+# that this is no longer needed.
 define_hook_label(scheme_to_interface_call)
 define_debugging_label(scheme_to_interface_call)
-       OP(pop,q)       REG(rbx)                        # arg1 = ret. add
-       OP(add,q)       TW(IMM(4),REG(rbx))             # Skip format info
+       nop
 #      jmp     scheme_to_interface
 \f
 # scheme_to_interface passes control from compiled Scheme code to a