Changeset 5889
- Timestamp:
- Feb 10, 2007, 11:00:08 PM (18 years ago)
- File:
-
- 1 edited
-
trunk/ccl/examples/objc-runtime.lisp (modified) (31 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/ccl/examples/objc-runtime.lisp
r5865 r5889 108 108 109 109 110 (let* ((objc-class-map (make-splay-tree #'%ptr-eql 111 #'(lambda (x y) 112 (< (the (unsigned-byte 32) 113 (%ptr-to-int x)) 114 (the (unsigned-byte 32) 115 (%ptr-to-int Y)))))) 116 (objc-metaclass-map (make-splay-tree #'%ptr-eql 117 #'(lambda (x y) 118 (< (the (unsigned-byte 32) 119 (%ptr-to-int x)) 120 (the (unsigned-byte 32) 121 (%ptr-to-int Y)))))) 110 (defun %ptr< (x y) 111 (< (the (unsigned-byte #+64-bit-target 64 #+32-bit-target 32) 112 (%ptr-to-int x)) 113 (the (unsigned-byte #+64-bit-target 64 #+32-bit-target 32) 114 (%ptr-to-int Y)))) 115 116 (let* ((objc-class-map (make-splay-tree #'%ptr-eql #'%ptr<)) 117 (objc-metaclass-map (make-splay-tree #'%ptr-eql #'%ptr<)) 122 118 ;;; These are NOT lisp classes; we mostly want to keep track 123 119 ;;; of them so that we can pretend that instances of them 124 120 ;;; are instances of some known (declared) superclass. 125 (private-objc-classes (make-splay-tree #'%ptr-eql 126 #'(lambda (x y) 127 (< (the (unsigned-byte 32) 128 (%ptr-to-int x)) 129 (the (unsigned-byte 32) 130 (%ptr-to-int Y)))))) 121 (private-objc-classes (make-splay-tree #'%ptr-eql #'%ptr<)) 131 122 (objc-class-lock (make-lock)) 132 123 (next-objc-class-id 0) 133 124 (next-objc-metaclass-id 0) 134 125 (class-table-size 1024) 135 (c (make-array 1024))136 (m (make-array 1024))126 (c (make-array class-table-size)) 127 (m (make-array class-table-size)) 137 128 (cw (make-array 1024 :initial-element nil)) 138 129 (mw (make-array 1024 :initial-element nil)) … … 289 280 290 281 ;;; Open shared libs. 291 #+darwin ppc-target282 #+darwin-target 292 283 (progn 293 284 (defloadvar *cocoa-event-process* *initial-process*) … … 438 429 439 430 (defloadvar *NSConstantString-class* 440 #+apple-objc441 (foreign-symbol-address "__NSConstantStringClassReference")442 #+gnu-objc443 431 (with-cstrs ((name "NSConstantString")) 444 (#_objc_lookup_class name))) 432 #+apple-objc (#_objc_lookUpClass name) 433 #+gnu-objc (#_objc_lookup_class name))) 445 434 446 435 … … 473 462 (defconstant JMP-r14 #x18 "offset of r14 (which we clobber) in jmp_buf") 474 463 (defconstant JMP-r15 #x20 "offset of r15 (which we also clobber) in jmp_buf")) 464 465 ;;; These constants also come from Libc sources. Hey, who needs 466 ;;; header files ? 467 #+x8664-target 468 (progn 469 (defconstant JB-RBX 0) 470 (defconstant JB-RBP 8) 471 (defconstant JB-RSP 16) 472 (defconstant JB-R12 24) 473 (defconstant JB-R13 32) 474 (defconstant JB-R14 40) 475 (defconstant JB-R15 48) 476 (defconstant JB-RIP 56) 477 (defconstant JB-RFLAGS 64) 478 (defconstant JB-MXCSR 72) 479 (defconstant JB-FPCONTROL 76) 480 (defconstant JB-MASK 80) 481 ) 482 483 475 484 476 485 … … 484 493 ;;; place. 485 494 495 #+ppc-target 486 496 (macrolet ((ppc-lap-word (instruction-form) 487 497 (uvref (uvref (compile nil … … 503 513 p))) 504 514 515 #+x8664-target 516 (defloadvar *setjmp-catch-rip-code* 517 (let* ((code-bytes '(#x4c #x89 #xe6 ; movq %r12, %rsi 518 #xff #xd3)) ; call *%rbx 519 (nbytes (length code-bytes)) 520 (p (malloc nbytes))) 521 (dotimes (i nbytes p) 522 (setf (%get-unsigned-byte p i) (pop code-bytes))))) 523 524 505 525 ;;; Catch frames are allocated on a stack, so it's OK to pass their 506 526 ;;; addresses around to foreign code. … … 515 535 ;;; an empty C stack frame from which the callback will be called. 516 536 537 #+ppc-target 517 538 (defun %associate-jmp-buf-with-catch-frame (jmp-buf catch-frame c-frame) 518 539 (%set-object jmp-buf JMP-sp c-frame) … … 523 544 (%get-ptr jmp-buf JMP-r14) throw-to-catch-frame) 524 545 t) 546 547 #+x8664-target 548 (defun %associate-jmp-buf-with-catch-frame (jmp-buf catch-frame c-frame) 549 (setf (%get-ptr jmp-buf JB-rbx) throw-to-catch-frame 550 (%get-ptr jmp-buf JB-rip) *setjmp-catch-rip-code*) 551 (%set-object jmp-buf JB-RSP c-frame) 552 (%set-object jmp-buf JB-RBP c-frame) 553 (%set-object jmp-buf JB-r12 catch-frame) 554 t) 555 525 556 526 557 ) … … 962 993 ;;; - Lisp numbers => SINGLE-FLOAT when possible 963 994 964 (def macrocoerce-to-bool (x)995 (defun coerce-to-bool (x) 965 996 (let ((x-temp (gensym))) 966 997 `(let ((,x-temp ,x)) 967 (if (or (eq ,x-temp 0) (null ,x-temp)) #.#$NO #.#$YES)))) 968 969 (defmacro coerce-to-address (x) 998 (if (or (eq ,x-temp 0) (null ,x-temp)) 999 #.#$NO 1000 #.#$YES)))) 1001 1002 (declaim (inline %coerce-to-bool)) 1003 (defun %coerce-to-bool (x) 1004 (if (and x (not (eql x 0))) 1005 #$YES 1006 #$NO)) 1007 1008 (defun coerce-to-address (x) 970 1009 (let ((x-temp (gensym))) 971 1010 `(let ((,x-temp ,x)) … … 974 1013 (t ,x-temp))))) 975 1014 976 (defmacro coerce-to-foreign-type (x ftype) 1015 ;;; This is generally a bad idea; it forces us to 1016 ;;; box intermediate pointer arguments in order 1017 ;;; to typecase on them, and it's not clear to 1018 ;;; me that it offers much in the way of additional 1019 ;;; expressiveness. 1020 (declaim (inline %coerce-to-address)) 1021 (defun %coerce-to-address (x) 1022 (etypecase x 1023 (macptr x) 1024 (string (%make-nsstring x)) ; does this ever get released ? 1025 (null (%null-ptr)))) 1026 1027 (defun coerce-to-foreign-type (x ftype) 977 1028 (cond ((and (constantp x) (constantp ftype)) 978 1029 (case ftype … … 982 1033 ((constantp ftype) 983 1034 (case ftype 984 (:id `( coerce-to-address ,x))985 (:<BOOL> `( coerce-to-bool ,x))1035 (:id `(%coerce-to-address ,x)) 1036 (:<BOOL> `(%coerce-to-bool ,x)) 986 1037 (t x))) 987 1038 (t `(case ,(if (atom ftype) ftype) 988 (:id ( coerce-to-address ,x))989 (:<BOOL> ( coerce-to-bool ,x))1039 (:id (%coerce-to-address ,x)) 1040 (:<BOOL> (%coerce-to-bool ,x)) 990 1041 (t ,x))))) 991 1042 992 1043 (defun objc-arg-coerce (typespec arg) 993 (coerce-to-foreign-type arg typespec)) 1044 (case typespec 1045 (:<BOOL> `(%coerce-to-bool ,arg)) 1046 (:id `(%coerce-to-address ,arg)) 1047 (t arg))) 994 1048 995 1049 … … 1035 1089 #+apple-objc 1036 1090 (funcall (ftd-ff-call-expand-function *target-ftd*) 1037 `( external-call "_objc_msgSend")1038 `(: id,receiver :<SEL> (@selector ,selector-name) ,@argspecs)1091 `(%ff-call (%reference-external-entry-point (load-time-value (external "_objc_msgSend")))) 1092 `(:address ,receiver :<SEL> (@selector ,selector-name) ,@argspecs) 1039 1093 :arg-coerce 'objc-arg-coerce 1040 1094 :result-coerce 'objc-result-coerce) … … 1051 1105 (funcall (ftd-ff-call-expand-function *target-ftd*) 1052 1106 `(%ff-call ,imp) 1053 `(: id,receiver :<SEL> (@selector ,selector-name) ,@argspecs)1107 `(:address ,receiver :<SEL> (@selector ,selector-name) ,@argspecs) 1054 1108 :arg-coerce 'objc-arg-coerce 1055 1109 :result-coerce 'objc-result-coerce)))) … … 1084 1138 (entry-name (if (funcall (ftd-ff-call-struct-return-by-implicit-arg-function *target-ftd*) return-typespec) 1085 1139 "_objc_msgSend_stret" 1086 "_objc -msgSend")))1140 "_objc_msgSend"))) 1087 1141 (funcall (ftd-ff-call-expand-function *target-ftd*) 1088 `(%ff-call ( external ,entry-name))1089 `(,structptr :id,receiver :<SEL> (@selector ,selector-name) ,@argspecs)1142 `(%ff-call (%reference-external-entry-point (load-time-value (external ,entry-name)))) 1143 `(,structptr :address ,receiver :<SEL> (@selector ,selector-name) ,@argspecs) 1090 1144 :arg-coerce 'objc-arg-coerce 1091 1145 :result-coerce 'objc-result-coerce)) … … 1102 1156 , (funcall (ftd-ff-call-expand-function *target-ftd*) 1103 1157 `(%ff-call ,imp) 1104 `(,structptr : id ,:<SEL> ,s ,@argspecs)1158 `(,structptr :address ,receiver :<SEL> ,s ,@argspecs) 1105 1159 :arg-coerce 'objc-arg-coerce 1106 1160 :result-coerce 'objc-result-coerce)))) … … 1115 1169 #+apple-objc 1116 1170 (funcall (ftd-ff-call-expand-function *target-ftd*) 1117 `(%ff-call ( external "_objc_msgSendSuper"))1171 `(%ff-call (%reference-external-entry-point (load-time-value (external "_objc_msgSendSuper")))) 1118 1172 `(:address ,super :<SEL> (@selector ,selector-name) ,@argspecs) 1119 1173 :arg-coerce 'objc-arg-coerce … … 1142 1196 (entry-name (if (funcall (ftd-ff-call-struct-return-by-implicit-arg-function *target-ftd*) return-typespec) 1143 1197 "_objc_msgSendSuper_stret" 1144 "_objc -msgSendSuper")))1198 "_objc_msgSendSuper"))) 1145 1199 (funcall (ftd-ff-call-expand-function *target-ftd*) 1146 `(%ff-call ( external ,entry-name))1200 `(%ff-call (%reference-external-entry-point (load-time-value (external ,entry-name)))) 1147 1201 `(,structptr :address ,super :<SEL> (@selector ,selector-name) ,@argspecs) 1148 1202 :arg-coerce 'objc-arg-coerce … … 1176 1230 ) 1177 1231 1232 1233 1178 1234 ;;; The first 13 fp arguments get passed in F1-F13 (and also "consume" 1179 1235 ;;; a GPR or two.) It's certainly possible for an FP arg and a non- 1180 1236 ;;; FP arg to share the same "offset", and parameter offsets aren't 1181 1237 ;;; strictly increasing. 1238 #+ppc-target 1182 1239 (defvar *objc-fpr-offsets* 1183 1240 #+32-bit-target … … 1257 1314 (format nil "^~a" (encode-objc-type element-type)))))) 1258 1315 (t (break "type = ~s" type))))))) 1259 1316 1317 #+ppc-target 1260 1318 (defun encode-objc-method-arglist (arglist result-spec) 1261 1319 (let* ((gprs-used 0) … … 1284 1342 (incf gprs-used 2)) 1285 1343 (foreign-single-float-type 1286 (setq size 4offset (current-fpr-arg-offset))1344 (setq size target::node-size offset (current-fpr-arg-offset)) 1287 1345 (incf fprs-used) 1288 1346 (incf gprs-used 1)) … … 1294 1352 (setq size (ceiling bits 8) 1295 1353 offset (current-gpr-arg-offset)) 1296 (incf gprs-used (ceiling bits 32))))1354 (incf gprs-used (ceiling bits target::nbits-in-word)))) 1297 1355 ((or foreign-record-type foreign-array-type) 1298 1356 (let* ((bits (ensure-foreign-type-bits arg))) 1299 1357 (setq size (ceiling bits 8) 1300 1358 offset (current-gpr-arg-offset)) 1301 (incf gprs-used (ceiling bits 32))))1359 (incf gprs-used (ceiling bits target::nbits-in-word)))) 1302 1360 (t (break "argspec = ~s, arg = ~s" argspec arg))) 1303 1361 (push (list (encode-objc-type arg) offset size) result)))))))) … … 1307 1365 arg-info)) 1308 1366 objc-forwarding-stack-offset))) 1367 (format nil "~a~d~:{~a~d~}" 1368 (encode-objc-type 1369 (parse-foreign-type result-spec)) 1370 max-parm-end 1371 arg-info)))) 1372 1373 #+x8664-target 1374 (defun encode-objc-method-arglist (arglist result-spec) 1375 (let* ((offset 0) 1376 (arg-info 1377 (let* ((result nil)) 1378 (dolist (argspec arglist (nreverse result)) 1379 (let* ((arg (parse-foreign-type argspec)) 1380 (delta 8)) 1381 (typecase arg 1382 (foreign-double-float-type) 1383 (foreign-single-float-type) 1384 ((or foreign-pointer-type foreign-array-type)) 1385 (foreign-integer-type) 1386 (foreign-record-type 1387 (let* ((bits (ensure-foreign-type-bits arg))) 1388 (setq delta (ceiling bits 8)))) 1389 (t (break "argspec = ~s, arg = ~s" argspec arg))) 1390 (push (list (encode-objc-type arg) offset) result) 1391 (setq offset (* 8 (ceiling (+ offset delta) 8)))))))) 1392 (let* ((max-parm-end offset)) 1309 1393 (format nil "~a~d~:{~a~d~}" 1310 1394 (encode-objc-type … … 1537 1621 (call type) 1538 1622 (case type 1539 (:<BOOL> (call `( coerce-to-bool ,arg)))1540 (:id (call `( coerce-to-address ,arg)))1623 (:<BOOL> (call `(%coerce-to-bool ,arg))) 1624 (:id (call `(%coerce-to-address ,arg))) 1541 1625 (otherwise (call arg))))) 1542 1626 ;; all "init" messages return :id … … 1608 1692 init-info))) 1609 1693 1610 (defun send-init-message-with-info (instance init-info args) 1611 (let* ((selector (objc-init-message-info-selector init-info)) 1612 (alist (objc-init-message-info-method-signature-alist init-info)) 1613 (pair (do* ((alist alist (cdr alist))) 1614 ((null (cdr alist)) 1615 (car alist) 1616 (let* ((pair (car alist))) 1617 (dolist (class (cdr pair)) 1618 (when (typep instance class) 1619 (return pair)))))))) 1620 (with-ns-exceptions-as-errors 1621 (apply (objc-init-method-signature-info-function (car pair)) 1622 instance 1623 selector 1624 args)))) 1694 1625 1695 1626 1696 … … 1640 1710 "Maps from lists of init keywords to OBJC-INIT-MESSAGE structures") 1641 1711 1642 (defun send-objc-init-message-with-info (instance init-info args) 1643 (let* ((selector (objc-init-message-info-selector init-info)) 1644 (alist (objc-init-message-info-method-signature-alist init-info)) 1645 (pair (do* ((alist alist (cdr alist))) 1646 ((null (cdr alist)) 1647 (car alist) 1648 (let* ((pair (car alist))) 1649 (dolist (class (cdr pair)) 1650 (when (typep instance class) 1651 (return pair)))))))) 1652 (with-ns-exceptions-as-errors 1653 (apply (objc-init-method-signature-info-function (car pair)) 1654 instance 1655 selector 1656 args)))) 1712 1713 1714 1657 1715 1658 1716 … … 1668 1726 (send-objc-init-message-with-info instance info args))) 1669 1727 1670 (defun allocate-objc-object (class) 1671 (send class 'alloc)) 1728 1672 1729 1673 1730 … … 2069 2126 #+gnu-objc (#_method_get_number_of_arguments m)) 2070 2127 2071 #+ apple-objc2128 #+(and apple-objc (not apple-objc-2.0)) 2072 2129 (progn 2073 2130 (defloadvar *original-deallocate-hook* … … 2118 2175 `(let ((,pool-temp (create-autorelease-pool))) 2119 2176 (unwind-protect 2120 ,@body2177 (progn ,@body) 2121 2178 (release-autorelease-pool ,pool-temp))))) 2122 2179 … … 2137 2194 (:pointers (:array :address 4))))) 2138 2195 2139 ;;; Apple's mechanism for maintaining per-thread exception handler2140 ;;; state isn't thread safe, which suggests that we should probably2141 ;;; install our own callbacks via #_objc_exception_set_functions.2142 ;;; It's 2007.2143 2196 2144 2197 #+apple-objc-2.0 … … 2150 2203 (progn 2151 2204 (#_objc_exception_try_enter ,data) 2152 (catch ,data2205 (catch ,data 2153 2206 (with-c-frame ,cframe 2154 2207 (%associate-jmp-buf-with-catch-frame … … 2201 2254 2202 2255 2256 (defun send-objc-init-message-with-info (instance init-info args) 2257 (let* ((selector (objc-init-message-info-selector init-info)) 2258 (alist (objc-init-message-info-method-signature-alist init-info)) 2259 (pair (do* ((alist alist (cdr alist))) 2260 ((null (cdr alist)) 2261 (car alist) 2262 (let* ((pair (car alist))) 2263 (dolist (class (cdr pair)) 2264 (when (typep instance class) 2265 (return pair)))))))) 2266 (with-ns-exceptions-as-errors 2267 (apply (objc-init-method-signature-info-function (car pair)) 2268 instance 2269 selector 2270 args))))
Note:
See TracChangeset
for help on using the changeset viewer.
