Changeset 5933


Ignore:
Timestamp:
Feb 14, 2007, 1:35:41 AM (18 years ago)
Author:
Gary Byers
Message:

Update for 070214 snapshots.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/ccl/release-notes.txt

    r5666 r5933  
    1 OpenMCL 1.1-pre-061231
     1OpenMCL 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))
     2251995065244
     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
     260openmcl 1.1-pre-061231
    2261- The FASL version changed (old FASL files won't work with this
    3262  lisp version), as did the version information which tries to
Note: See TracChangeset for help on using the changeset viewer.