Changeset 5933
- Timestamp:
- Feb 14, 2007, 1:35:41 AM (18 years ago)
- File:
-
- 1 edited
-
trunk/ccl/release-notes.txt (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/ccl/release-notes.txt
r5666 r5933 1 OpenMCL 1.1-pre-061231 1 OpenMCL 1.1-pre-070214 2 - The FASL version changed (old FASL files won't work with this 3 lisp version), as did the version information which tries to 4 keep the kernel in sync with heap images. 5 - There are new interface files for all platforms. These files 6 encode some foreign type information a little differently 7 than older ones did (notably information about foreign functions 8 that return structures or accept structure args by value.) The 9 new .cdb files can't be used by older versions of OpenMCL; using 10 older .cdb files with this version is "allowed, but not supported 11 or recommended." 12 - Almost all of the changes in functionality since the last (061231) 13 snapshots and since the CVS freeze on 070117 have to do with 14 relatively obscure issues having to do with passing structures 15 to foreign functions by value and/or returning structures from foreign 16 function calls. 17 18 These idioms are fairly rare in traditional C code (though it's 19 fairly common to pass -pointers- to structures by reference 20 and sometimes to return pointers to structures. (There are 21 a few C compiler runtime routines that perform some flavor 22 of integer division and return a two-element structure that 23 contains "quotient" and "remainder" fields, but that's typically 24 about the extent of the use of this idiom.) The idioms are used 25 much more often in Apple's Carbon and Cooca libraries and in 26 some of the frameworks (CoreGraphics, CoreFoundation) that those 27 libraries are based on. 28 29 OpenMCL's FFI has provided some support for this in the past; 30 notably, it's provided support for (most of the) structure-returning 31 and struct-by-value conventions used on 32-bit PPC Darwin. In these 32 conventions, a foreign function that returned a structure received 33 a pointer to an instance of that structure type as a first argument, 34 and a function that received a structure argument by value received 35 the structure's contents in 32-bit word-size integer chunks (regardless 36 of the types or sizes of the structure's fields.) Knowledge of these 37 conventions was hardwired into various parts of the system (e.g., 38 the interface database), so that it was not generally possible to 39 tell whether a given foreign function returned a structure type 40 (or just happened to take an extra pointer argument.) 41 42 Unfortunately, there are at least 4 other sets of conventions for 43 dealing with structure arguments/return values on the platforms 44 that OpenMCL runs on (and even the DarwinPPC32 conventions weren't 45 fully/correctly implemented.) OpenMCL's FFI is generally pretty 46 low-level, but to the extent that it's reasonable to talk about 47 "higher level" constructs (EXTERNAL-CALL, SEND, FF-CALL, #_), those 48 higher-level constructs try to enforce uniform syntax and try 49 to hide the platform-specific details in backend-specific functions. 50 51 The impact of these changes should generally be pretty minimal. 52 In a "higher-level" construct used to call a foreign function that 53 returns a structure type, the first parameter in the call should 54 be a pointer to an instance of that structure type. 55 56 For example, if a :rect structure is defined as: 57 58 (def-foreign-type nil 59 (:struct :rect 60 (:width :int) 61 (:height :int) 62 (:x :int) ; x coordinate of origin 63 (:y :int))) 64 65 and a foreign function named "inset_rect" takes a rect and an integer 66 delta and returns a new :rect "inset" by that delta, a call to that 67 foreign function might look like: 68 69 (rlet ((result :rect)) 70 (ff-call *address-of-inset-rect* result (:struct :rect) r :int delta :(:struct rect)) 71 ;; or, if "inset_rect" was declared in the interface database: 72 (#_inset_rect result r delta)) 73 74 75 A callback that returns a :rect likewise should accept a pointer 76 to an instance of the :rect type as a first (unqualified) argument 77 and explicitly declare that it returns a (:STRUCT :RECT). 78 79 (defcallback *address-of-inset-rect (result (:struct :rect) r :int delta (:struct :rect)) 80 (setf (pref result :rect.x) (+ (pref r :rect.x) delta) 81 (pref result :rect.y) (+ (pref r :rect.y) delta) 82 (pref result :rect.width) (- (pref r :rect.width) (* 2 delta)) 83 (pref result :rect.height) (- (pref r :rect.height) (* 2 delta)))) 84 85 Note that this is very similar to what's been (implicitly) supported 86 on DarwinPPC32; the basic difference is that the return type 87 ("(:STRUCT :RECT)") is explicitly specified (or, in the case of #_, 88 specified in the interface database). Whether the "result" pointer 89 is actually passed as an argument or not is platform-dependent (on 90 DarwinPPC64, the :rect structure would be "returned" by returning 91 4 :int values in 4 different machine registers), but the same syntax 92 can be used (and hides those details) on all platforms. 93 94 In the examples above, we said that the (presumed source) rectangle 95 was passed by value as a value of type (:struct :rect), and we let 96 the FFI deal with the details. Historically, this parameter could 97 have been specified as a small unsigned integer N (denoting the 98 DarwinPPC32 convention of passing the structure value a N 99 native-word-size integer arguments.) Again, there are several 100 different conventions for passing and receiving structure values, 101 and it's best to let the FFI decide how to follow those conventions. 102 (Some of those conventions are quite complicated, and depend on 103 the size of the structure as well as the types of its fields.) 104 105 In all cases, a callback which declares a parameter to be of a 106 structure type can treat that parameter as a pointer an instance of 107 that structure type with fields initialized by the caller (as in 108 the case of "r" in the example above.) 109 110 In the ObjC bridge, the DEFINE-OBJC-METHOD macro has always provided 111 syntax for specifiying that the method "returns" a structure. (That 112 syntax is (:struct <struct-type> <parameter-name>). That continues 113 to be supported. 114 115 Apple's ObjC runtime provides different functions (#_objc_msgSend and 116 #_objc_msgSend_stret) to handle the cases of sending messages which 117 return non-structure and structure results. These low-level functions 118 are very sensitive to whether the structure is actually returned via 119 an "invisible" first argument or not (this is only one of a few different 120 conventions on some platforms.) OpenMCL's ObjC bridge makes similar 121 distinctions, but uses simple, consistent rules: a message that returns 122 a structure should always be sent via SEND/STRET (or some variant of 123 SEND/STRET) and should have a first parameter of type "pointer to 124 returned structure type", regardless of whether or not that pointer 125 is actually passed to the method implementation or just used as by 126 some platform-specific code to transfer register values.) 127 128 The end result of all of this (several weeks of bootstrapping) is 129 that most things are pretty much the same, at least on DarwinPPC32; 130 only foreign function calls/callbacks that involve passing structures 131 by value or returning structures need change at all, and the changes 132 generally involve being more explicit/declarative about what's going 133 on. These changes -do- allow these idioms to be used on other 134 (64-bit) platforms, and since they're heavily used in Apple GUI 135 libraries and since 64-bit versions of Carbon and Cocoa are announced 136 features of Leopard, it seemed appropriate to get support for this 137 stuff into the FFI on those platforms and to try to do it in a way 138 that hid the platform-dependent details. (I didn't expect all of 139 this to take so long.) 140 141 - The initial listener PROCESS now persists across SAVE-APPLICATION. 142 This means that (for instance): 143 144 ? (defvar *listener-process* (current-process)) 145 *LISTENER-PROCESS* 146 ? (save-application "new.image") 147 shell> openmcl new.image 148 ? (eq (current-process) *listener-process*) 149 T 150 ;; though of course the underlying OS thread, stacks, etc are unlikely 151 ;; to be "equal" in any sense. 152 153 The current process is sometimes used to mark "ownership" of thread-private 154 hash-tables and streams. (Even though it doesn't make much sense for 155 STREAMs to persist across SAVE-APPLICATION, it does make sense for 156 HASH-TABLEs to do so; HASH-TABLES created with the :PRIVATE T option 157 and "owned" by the initial listener process continue to be owned by 158 that the current listener process in the new image.) 159 160 - All of the FFI changes above do seem to allow the Cocoa IDE example 161 to run on ppc64/x86-64 (as well as ppc32) under Leopard, and 162 hopefully that'll soon be true of applications generated via Mikel 163 Evins' Bosco system as well. The bridge and demo code have been 164 conditionalized to support ObjC 2.0 on 64-bit systems, to avoid 165 deprecated functions and methods, and to support 64-bit Cocoa 166 changes. Hopefully, this has been done in a way that doesn't break 167 PPC32 Cocoa under Tiger (he said, quickly rushing to the nearest 168 PPC32 Tiger machine and breathing a sigh of relief when the Cocoa 169 listener appeared ..) 64-bit Cocoa sometimes used 64-bit signed and 170 unsigned integers in place of 32-bit integers; accordingly, the 171 foreign types :<NSI>nteger and :<NSUI>nteger are defined (as 32-bit 172 signed/unsigned integers) on 32-bit platforms, and these types are 173 used in some method and type definitions. (Those integer types are 174 predefined in Objc 2.0, and are 64 bits wide on 64-bit platforms.) 175 176 More pervasively (and a little more problematically), CoreGraphics 177 (and things built on top of it, including Cocoa) uses double-floats 178 instead of single-floats for many things on 64-bit hardware; the 179 difference is abstracted (a little) via the new CGFloat type. 180 This means that (for instance) code which initializes a constant-sized 181 NSRect on a 32-bit machines and has traditionally done so via 182 something like: 183 184 (ns-make-rect 0.0 0.0 500.0 200.0) 185 186 now needs to do something like: 187 188 (ns-make-rect (float 0.0 ccl::+cgfloat-zero+) ..) 189 190 in order to compile and run on both 32-bit and 64-bit platforms. 191 192 where ccl::+cgfloat-zero+ is defined as 1.0f0 on 32-bit platforms 193 and as 1.0d0 on 64-bit machines. Cases involving constants won't 194 incur any runtime overhead and the occasional runtime overhead in 195 other cases -probably- isn't that great in context (compared to 196 initializing a view hierarchy ...) but it's certainly ugly to 197 look at. It's possible that some of this ugliness could be 198 hidden in the bridge/FFI (by making them do the necessary coercions 199 for you), but there are tradeoffs there. 200 201 - The ObjC bridge has had a long-standing bug whereby a standalone 202 Cocoa application may have needed to find the interface databases 203 at runtime in order for MAKE-OBJC-INSTANCE and MAKE-INSTANCE of 204 an ObjC class to work. (These functions needed to be able to 205 send an "init" message to the newly-allocated instance, and needed 206 to know the type signature of that init message in order to do that.) 207 The current scheme tries to avoid this by pre-compiling helper 208 functions to enable calling all known "init" message signatures. 209 (More accurately, all fixed-argument "init" message signatures.) 210 This scheme avoids the need to send messages whose argument 211 and result types are computed at runtime (via %SEND), and %SEND 212 (a) was known to be inefficient and (b) would have a lot of 213 difficulty handling all known structure return/passing conventions 214 on supported platforms. Accordingly, %SEND has been deprecated 215 (with extreme prejudice, e.g., removed.) 216 217 - a couple of little functions are defined (but their names are 218 not yet exported) on x86-64: ccl::rdtsc and ccl::rdtsc64 provide 219 access to the values returned by on-chip cycle counting instructions. 220 For instance: 221 222 ? (let* ((start (ccl::rdtsc))) 223 (sleep 1) 224 (- (ccl::rdtsc) start)) 225 1995065244 226 227 Hmm. Apparently, the 2.0GHz MacBook I tried that on is actually 228 a 1.995GHz MacBook. 229 230 There are all kinds of ways for rdtsc to lose (and return 231 inaccurate or misleading results): the cycle counters for 232 each CPU core in a multi-core system aren't necessarily 233 kept in sync, and many modern systems allow CPU clock rates 234 to vary (for power-management reasons) and/or allow the CPU 235 to sleep/hibernate. OSes seem to offer some support for 236 compensating for these effects, and it seems like ccl::rdtsc 237 and ccl::rdtsc64 can be used to obtain interesting results. 238 239 The RDTSC instruction actually returns an unsigned 64-bit 240 result; apparently, some Intel documentation claims that this 241 value will not "wrap around" to 0 at contemporary clock rates 242 for at least 10 years after the system was booted. (If you can 243 keep an Intel system running for 9 years between reboots, you 244 might consider telling Intel that the RDTSC counter wrapped around 245 a year early; they might give you a refund. Or maybe not.) 246 A non-negative OpenMCL64 fixnum is limited to 60 bits; the 247 ccl::rdtsc function truncates the 64-bit counter value so 248 that it fits in a non-negative fixnum; if the 10 year limit 249 for the 64-bit value is accurate, the 60-bit value would 250 wrap around after about 223 days of uptime. 251 252 ccl::rdtsc64 returns the full 64-bit counter value, but 253 may return a bignum after 223 days of uptime. 254 255 - lots of bug fixes (not all of which involved the FFI or ObjC 256 bridge.) 257 258 259 260 openmcl 1.1-pre-061231 2 261 - The FASL version changed (old FASL files won't work with this 3 262 lisp version), as did the version information which tries to
Note:
See TracChangeset
for help on using the changeset viewer.
