Changeset 5728
- Timestamp:
- Jan 18, 2007, 3:10:33 AM (18 years ago)
- File:
-
- 1 edited
-
trunk/ccl/examples/objc-runtime.lisp (modified) (21 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/ccl/examples/objc-runtime.lisp
r5696 r5728 45 45 (progn 46 46 (use-interface-dir :cocoa) 47 #-apple-objc-2.048 47 (use-interface-dir :carbon)) ; need :carbon for things in this file 49 48 #+gnu-objc … … 62 61 (defloadvar *NSApp* nil ) 63 62 63 ;;; Apple ObjC 2.0 provides (#_objc_getProtocol name). In other 64 ;;; runtimes, there doesn't seem to be any way to find a Protocol 65 ;;; object given its name. We need to be able to ask at runtime 66 ;;; whether a given object conforms to a protocol in order to 67 ;;; know when a protocol method is ambiguous, at least when the 68 ;;; message contains ambiguous methods and some methods are protocol 69 ;;; methods 70 (defloadvar *objc-protocols* (make-hash-table :test #'equal)) 71 72 (defun lookup-objc-protocol (name) 73 (values (gethash name *objc-protocols*))) 64 74 65 75 (defun ensure-objc-classptr-resolved (classptr) … … 68 78 (unless (logtest #$_CLS_RESOLV (pref classptr :objc_class.info)) 69 79 (external-call "__objc_resolve_class_links" :void))) 80 70 81 71 82 … … 451 462 #|(defconstant JMP-ctr #x5c "count register jmp_buf offset")|# 452 463 (defconstant JMP-sp 0 "stack pointer offset in jmp_buf") 453 (defconstant JMP-r1 3 8 "offset of r13(which we clobber) in jmp_buf")454 (defconstant JMP-r1 4 12"offset of r14 (which we also clobber) in jmp_buf"))464 (defconstant JMP-r14 12 "offset of r14 (which we clobber) in jmp_buf") 465 (defconstant JMP-r15 16 "offset of r14 (which we also clobber) in jmp_buf")) 455 466 456 467 #+ppc64-target … … 459 470 #|(defconstant JMP-ctr #x5c "count register jmp_buf offset")|# 460 471 (defconstant JMP-sp 0 "stack pointer offset in jmp_buf") 461 (defconstant JMP-r13 #x10 "offset of r13 (which we clobber) in jmp_buf") 462 (defconstant JMP-r14 #x18 "offset of r14 (which we also clobber) in jmp_buf")) 472 (defconstant JMP-r13 #x10 "offset of r13 (which we preserve) in jmp_buf") 473 (defconstant JMP-r14 #x18 "offset of r14 (which we clobber) in jmp_buf") 474 (defconstant JMP-r15 #x20 "offset of r15 (which we also clobber) in jmp_buf")) 463 475 464 476 465 ;;; A malloc'ed pointer to two words of machine code. The first 466 ;;; instruction (rather obviously) copies r13 to r4. A C function 467 ;;; passes its second argument in r4, but since r4 isn't saved in a 468 ;;; jmp_buf, we have to do this copy. The second instruction just 469 ;;; jumps to the address in the count register, which is where we 470 ;;; really wanted to go in the first place. 477 ;;; A malloc'ed pointer to thre words of machine code. The first 478 ;;; instruction copies the address of the trampoline callback from r14 479 ;;; to the count register. The second instruction (rather obviously) 480 ;;; copies r15 to r4. A C function passes its second argument in r4, 481 ;;; but since r4 isn't saved in a jmp_buf, we have to do this copy. 482 ;;; The second instruction just jumps to the address in the count 483 ;;; register, which is where we really wanted to go in the first 484 ;;; place. 471 485 472 486 (macrolet ((ppc-lap-word (instruction-form) … … 475 489 (ppc-lap-function () ((?? 0)) 476 490 ,instruction-form))) 477 0) 0)))491 0) #+ppc64-target 1 #+ppc32-target 0))) 478 492 (defloadvar *setjmp-catch-lr-code* 479 493 (let* ((p (malloc 12))) 480 494 (setf (%get-unsigned-long p 0) (ppc-lap-word (mtctr 14)) 481 (%get-unsigned-long p 4) (ppc-lap-word (mr 4 1 3))495 (%get-unsigned-long p 4) (ppc-lap-word (mr 4 15)) 482 496 (%get-unsigned-long p 8) (ppc-lap-word (bctr))) 483 497 ;;; Force this code out of the data cache and into memory, so … … 499 513 ;;; wind up calling THROW-TO-CATCH-FRAME with the specified catch 500 514 ;;; frame as its second argument. The C frame used here is just 501 ;; an empty C stack frame from which the callback will be called.515 ;;; an empty C stack frame from which the callback will be called. 502 516 503 517 (defun %associate-jmp-buf-with-catch-frame (jmp-buf catch-frame c-frame) 504 518 (%set-object jmp-buf JMP-sp c-frame) 505 (%set-object jmp-buf JMP-r13 catch-frame) 519 (%set-object jmp-buf JMP-r15 catch-frame) 520 #+ppc64-target 521 (%set-object jmp-buf JMP-r13 (%get-os-context)) 506 522 (setf (%get-ptr jmp-buf JMP-lr) *setjmp-catch-lr-code* 507 523 (%get-ptr jmp-buf JMP-r14) throw-to-catch-frame) … … 565 581 (meta-id (objc-class-id->objc-metaclass-id i)) 566 582 (m (id->objc-metaclass meta-id))) 583 (let* ((class (make-objc-class-pair super (make-cstring (objc-class-id-foreign-name i)))) 584 (meta (pref class #+apple-objc :objc_class.isa 585 #+gnu-objc :objc-class.class_pointer))) 567 586 (unless (splay-tree-get metaclass-map m) 568 587 (%revive-macptr m) 569 (%setf-macptr m (%make-basic-meta-class 570 (make-cstring (objc-metaclass-id-foreign-name meta-id)) 571 super 572 (find-class 'ns::ns-object))) 588 (%setf-macptr m meta) 573 589 (splay-tree-put metaclass-map m meta-id)) 574 (%setf-macptr c (%make-class-object 575 m 576 super 577 (make-cstring (objc-class-id-foreign-name i)) 578 (%null-ptr) 579 0)) 580 590 (%setf-macptr c class)) 591 #+apple-objc-2.0 592 (%add-objc-class c) 593 #-apple-objc-2.0 581 594 (multiple-value-bind (ivars instance-size) 582 595 (%make-objc-ivars c) … … 1226 1239 (%get-signed-long method-vector 12) -1) 1227 1240 method-vector)) 1228 1241 1229 1242 1230 1243 ;;; Make a meta-class object (with no instance variables or class … … 1407 1420 (#___objc_exec_class m))) 1408 1421 1422 #+apple-objc-2.0 1423 (defun %add-objc-class (class) 1424 (#_objc_registerClassPair class)) 1409 1425 1410 1426 (defun %make-nsstring (string) … … 1435 1451 1436 1452 1437 #+apple-objc 1438 (defun zone-pointer-size (p) 1439 (with-macptrs ((zone (#_malloc_zone_from_ptr p))) 1440 (unless (%null-ptr-p zone) 1441 (let* ((size (ff-call (pref zone :malloc_zone_t.size) 1442 :address zone 1443 :address p 1444 :int))) 1445 (declare (fixnum size)) 1446 (unless (zerop size) 1447 size))))) 1453 1448 1454 1449 1455 (defun objc-private-class-id (classptr) … … 1451 1457 (when info 1452 1458 (or (private-objc-class-info-declared-ancestor info) 1453 (with-macptrs ((super (pref classptr :objc_class.super_class))) 1459 (with-macptrs ((super #+apple-objc-2.0 (#_class_getSuperclass classptr) 1460 #-apple-objc-2.0 (pref classptr :objc_class.super_class))) 1454 1461 (loop 1455 1462 (when (%null-ptr-p super) … … 1459 1466 (return (setf (private-objc-class-info-declared-ancestor info) 1460 1467 id)) 1461 (%setf-macptr super (pref super :objc_class.super_class)))))))))) 1468 (%setf-macptr super #+apple-objc-2.0 (#_class_getSuperclass super) 1469 #-apple-objc-2.0 (pref super :objc_class.super_class)))))))))) 1462 1470 1463 1471 (defun objc-class-or-private-class-id (classptr) … … 1467 1475 1468 1476 (defun %objc-instance-class-index (p) 1469 (if (with-macptrs (q) 1470 (safe-get-ptr p q) 1471 (not (%null-ptr-p q))) 1472 (with-macptrs ((parent #+apple-objc (pref p :objc_object.isa) 1473 #+gnu-objc (pref p :objc_object.class_pointer))) 1474 (or 1475 (objc-class-id parent) 1476 (objc-private-class-id parent))))) 1477 (unless (%null-ptr-p p) 1478 (if (with-macptrs (q) 1479 (safe-get-ptr p q) 1480 (not (%null-ptr-p q))) 1481 (with-macptrs ((parent #+apple-objc (pref p :objc_object.isa) 1482 #+gnu-objc (pref p :objc_object.class_pointer))) 1483 (or 1484 (objc-class-id parent) 1485 (objc-private-class-id parent)))))) 1477 1486 1478 1487 … … 1535 1544 1536 1545 (defun %add-objc-method (classptr selector typestring imp) 1537 #+apple-objc 1538 (#_class_addMethods classptr 1539 (%mlist-containing classptr selector typestring imp)) 1540 #+gnu-objc 1546 #+apple-objc-2.0 1547 (with-cstrs ((typestring typestring)) 1548 (or (not (eql #$NO (#_class_addMethod classptr selector imp typestring))) 1549 (let* ((m (if (objc-metaclass-p classptr) 1550 (#_class_getClassMethod classptr selector) 1551 (#_class_getInstanceMethod classptr selector)))) 1552 (if (not (%null-ptr-p m)) 1553 (#_method_setImplementation m imp) 1554 (error "Can't add ~s method to class ~s" selector typestring))))) 1555 #-apple-objc-2.0 1556 (progn 1557 #+apple-objc 1558 (#_class_addMethods classptr 1559 (%mlist-containing classptr selector typestring imp)) 1560 #+gnu-objc 1541 1561 ;;; We have to do this ourselves, and have to do it with the runtime 1542 1562 ;;; mutex held. 1543 (with-gnu-objc-mutex-locked (*gnu-objc-runtime-mutex*)1544 (let* ((ctypestring (make-cstring typestring))1545 (new-mlist nil))1546 (with-macptrs ((method (external-call "search_for_method_in_list"1547 :address (pref classptr :objc_class.methods)1548 :address selector1549 :address)))1550 (when (%null-ptr-p method)1551 (setq new-mlist (make-record :objc_method_list :method_count 1))1552 (%setf-macptr method (pref new-mlist :objc_method_list.method_list)))1553 (setf (pref method :objc_method.method_name) selector1554 (pref method :objc_method.method_types) ctypestring1555 (pref method :objc_method.method_imp) imp)1556 (if new-mlist1557 (external-call "GSObjCAddMethods"1558 :address classptr1559 :address new-mlist1560 :void)1561 (external-call "__objc_update_dispatch_table_for_class"1562 :address classptr1563 :void))))))1563 (with-gnu-objc-mutex-locked (*gnu-objc-runtime-mutex*) 1564 (let* ((ctypestring (make-cstring typestring)) 1565 (new-mlist nil)) 1566 (with-macptrs ((method (external-call "search_for_method_in_list" 1567 :address (pref classptr :objc_class.methods) 1568 :address selector 1569 :address))) 1570 (when (%null-ptr-p method) 1571 (setq new-mlist (make-record :objc_method_list :method_count 1)) 1572 (%setf-macptr method (pref new-mlist :objc_method_list.method_list))) 1573 (setf (pref method :objc_method.method_name) selector 1574 (pref method :objc_method.method_types) ctypestring 1575 (pref method :objc_method.method_imp) imp) 1576 (if new-mlist 1577 (external-call "GSObjCAddMethods" 1578 :address classptr 1579 :address new-mlist 1580 :void) 1581 (external-call "__objc_update_dispatch_table_for_class" 1582 :address classptr 1583 :void))))))) 1564 1584 1565 1585 (defvar *lisp-objc-methods* (make-hash-table :test #'eq)) … … 1758 1778 (rlet ((,super :objc_super 1759 1779 #+apple-objc :receiver #+gnu-objc :self ,self 1760 :class1780 #+apple-objc-2.0 :super_class #-apple-objc-2.0 :class 1761 1781 ,@(if class-p 1782 #+apple-objc-2.0 1783 `((external-call "_class_getSuperclass" 1784 :address (pref (@class ,class-name) :objc_class.isa) :address)) 1785 #-apple-objc-2.0 1762 1786 `((pref 1763 1787 (pref (@class ,class-name) … … 1765 1789 #+gnu-objc :objc_class.super_class ) 1766 1790 :objc_class.super_class)) 1791 #+apple-objc-2.0 1792 `((external-call "_class_getSuperclass" 1793 :address (@class ,class-name) :address)) 1794 #-apple-objc-2.0 1767 1795 `((pref (@class ,class-name) :objc_class.super_class))))) 1768 1796 (macrolet ((send-super (msg &rest args &environment env) … … 1793 1821 1794 1822 (defun class-get-instance-method (class sel) 1795 #+apple-objc (let* ((p (#_class_getInstanceMethod class sel))) 1796 (if (%null-ptr-p p) 1797 (unless (logtest #$CLS_INITIALIZED (pref (pref class :objc_class.isa) :objc_class.info)) 1798 ;; Do this for effect; ignore the :<IMP> it returns. 1799 ;; (It should cause the CLS_NEED_BIND flag to turn itself 1800 ;; off after the class has been initialized; we need 1801 ;; the class and all superclasses to have been initialized, 1802 ;; so that we can find category methods via 1803 ;; #_class_getInstanceMethod. 1804 (external-call "_class_lookupMethod" 1805 :id class 1806 :<SEL> sel 1807 :address) 1808 (%setf-macptr p (#_class_getInstanceMethod class sel)))) 1809 p) 1823 #+apple-objc (#_class_getInstanceMethod class sel) 1810 1824 #+gnu-objc (#_class_get_instance_method class sel)) 1811 1825 … … 1842 1856 :key #'function-name) 1843 1857 ) 1844 1845 ;;; Return a typestring and offset as multiple values.1846 1847 (defun objc-get-method-argument-info (m i)1848 #+apple-objc1849 (%stack-block ((type 4) (offset 4))1850 (#_method_getArgumentInfo m i type offset)1851 (values (%get-cstring (%get-ptr type)) (%get-signed-long offset)))1852 #+gnu-objc1853 (progn1854 (with-macptrs ((typespec (#_objc_skip_argspec (pref m :objc_method.method_types))))1855 (dotimes (j i (values (%get-cstring typespec)1856 (#_strtol (#_objc_skip_typespec typespec)1857 (%null-ptr)1858 10.)))1859 (%setf-macptr typespec (#_objc_skip_argspec typespec))))))1860 1858 1861 1859 … … 1893 1891 (%get-cstring cstring)))) 1894 1892 1893 #+apple-objc-2.0 1894 ;;; This isn't defined in headers; it's sort of considered a built-in 1895 ;;; type by the ObjC frontend. (See also the ObjC runtime source.) 1896 (eval-when (:compile_toplevel :execute) 1897 (def-foreign-type nil 1898 (:struct :_objc_exception_data 1899 (:buf :jmp_buf) 1900 (:pointers (:array :address 4))))) 1901 1902 ;;; Apple's mechanism for maintaining per-thread exception handler 1903 ;;; state isn't thread safe, which suggests that we should probably 1904 ;;; install our own callbacks via #_objc_exception_set_functions. 1905 ;;; It's 2007. 1906 1907 #+apple-objc-2.0 1908 (defmacro with-ns-exceptions-as-errors (&body body) 1909 (let* ((data (gensym)) 1910 (cframe (gensym))) 1911 `(rletZ ((,data :_objc_exception_data)) 1912 (unwind-protect 1913 (progn 1914 (#_objc_exception_try_enter ,data) 1915 (catch ,data 1916 (with-c-frame ,cframe 1917 (%associate-jmp-buf-with-catch-frame 1918 ,data 1919 (%fixnum-ref (%current-tcr) target::tcr.catch-top) 1920 ,cframe) 1921 (progn 1922 ,@body)))) 1923 (check-ns-exception ,data))))) 1924 1925 1926 1927 #-apple-objc-2.0 1895 1928 (defmacro with-ns-exceptions-as-errors (&body body) 1896 1929 #+apple-objc … … 1914 1947 ) 1915 1948 1916 #+apple-objc 1949 #+apple-objc-2.0 1950 (defun check-ns-exception (data) 1951 (with-macptrs ((exception (#_objc_exception_extract data))) 1952 (if (%null-ptr-p exception) 1953 (#_objc_exception_try_exit data) 1954 (error (ns-exception->lisp-condition (%inc-ptr exception 0)))))) 1955 1956 #+(and apple-objc (not apple-objc-2.0)) 1917 1957 (defun check-ns-exception (nshandler) 1918 1958 (with-macptrs ((exception (external-call "__NSExceptionObjectFromHandler2"
Note:
See TracChangeset
for help on using the changeset viewer.
