module: dm-internals synopsis: Functions for low-level access to the layout of dylan objects. author: Paul Howard Copyright: Original Code is Copyright (c) 1995-2004 Functional Objects, Inc. All rights reserved. License: Functional Objects Library Public License Version 1.0 Dual-license: GNU Lesser General Public License Warranty: Distributed WITHOUT WARRANTY OF ANY KIND ///// SLOT POSITIONS define constant $iclass-mm-wrapper-offset = 2; define constant $iclass-repeated-slot-descriptor = 3; define constant $iclass-instance-slot-descriptors-offset = 4; define constant $iclass-direct-superclasses-offset = 7; define constant $iclass-all-superclasses-offset = 8; define constant $iclass-direct-subclasses-offset = 13; define constant $iclass-direct-methods-offset = 14; define constant $iclass-direct-slot-descriptors-offset = 15; define constant $iclass-all-slot-descriptors-offset = 16; define constant $iclass-class-storage-offset = 21; ///// WRITE-DYLAN-VALUE // define method write-dylan-value (ap :: , address :: , value :: ) => (v :: , ok :: ) if (instance? (address, ) | page-write-permission? (ap.debug-target-access-path, address)) block () values (write-value (ap.debug-target-access-path, address, value), #t); exception (x :: ) values (as-remote-value(0), #f); end block; else let spy-thread = select-thread-for-spy(ap); let result = if (spy-thread) run-spy-on-thread (ap, spy-thread, ap.C-spy.write-location-through-barrier, address, value); else #f end if; if (result) values (result, #t); else values (as-remote-value(0), #f); end if; end if; end method; ///// READ-DYLAN-VALUE // define method read-dylan-value (ap :: , address :: ) => (v :: , ok :: ) // This is the quick method for reading a dylan value. This method can only be used // if it is known that there is no MM barrier on the address from which to read local method read-dylan-value-quick (ap, address) let val = as-remote-value(0); let success = #f; block () val := read-value (ap.debug-target-access-path, address); success := #t; exception (x :: ) val := as-remote-value(0); success := #f; end block; values (val, success); end method; // If this is the first read in a new debugger transaction then flush the cache if (ap.new-debugger-transaction?) ap.pages-safe-to-read-cache := make (); ap.new-debugger-transaction? := #f; end if; // A value can be read using the quick method if we know there is no MM barrier on // the address from which to read. MM barriers cover a whole page. The is no // barrier on an address when: // 1. The address is an active register // 2. The address's page is in the cache i.e. we've read from this page before in // the current transaction // 3. The address's page is not read-protected // If it is determined there is no barrier on a page, it is guaranteed that no // barrier will be placed on the page during the remainder of the transaction. // if (instance? (address, )) read-dylan-value-quick (ap, address); else let page-number = remote-address-page-number (ap.debug-target-access-path, address); if (member? (page-number, ap.pages-safe-to-read-cache)) read-dylan-value-quick (ap, address); else let (quick-val, quick-success) = read-dylan-value-quick(ap, address); if (page-read-permission? (ap.debug-target-access-path, address)) add! (ap.pages-safe-to-read-cache, page-number); values(quick-val, quick-success); else // We have to read this location via the spy, but there's no // point in even attempting this if the "quick" call resulted in // a remote-access-violation. The spy function will just // signal access-violations itself, and we don't want that. let spy-thread = select-thread-for-spy(ap); let result = if (spy-thread & quick-success) run-spy-on-thread (ap, spy-thread, ap.C-spy.read-location-through-barrier, address); else #f end if; if (result) add! (ap.pages-safe-to-read-cache, page-number); values (result, #t); else values(quick-val, quick-success); end if; end if; end if; end if; end method; /* ///// TEMPORARY DEFINITIONS define method read-dylan-value (application :: , address :: ) => (value :: , worked? :: ) let value = as-remote-value(0); let worked? = #f; block () value := read-value(application.debug-target-access-path, address); worked? := #t; exception (pants :: ) worked? := #f; value := as-remote-value(0); end block; values(value, worked?); end method; */ ///// TAGS // The DM is given knowledge of the dylan object tagging scheme employed // by the runtime. define constant $dylan-tag-pointer = 0; define constant $dylan-tag-integer = 1; define constant $dylan-tag-character = 2; define constant $dylan-tag-boolean = 3; define method inspect-instance-tag (application :: , instance :: ) => (tag-info :: ) remote-value-low-order-bits(instance, 2) end method; ///// READ-INSTANCE-HEADER // Given an instance of any dylan object, read the header field and // return it as a remote value. "ok" determines whether the read was // successful. define method read-instance-header (ap :: , object :: ) => (v :: , ok :: ) read-dylan-value (ap, indexed-remote-value (object, 0)); end method; ///// READ-INSTANCE-SLOT-ELEMENT // Given an instance of any dylan object, return the i'th slot value // as a define method read-instance-slot-element (ap :: , object :: , i :: ) => (v :: , ok :: ) read-dylan-value (ap, indexed-remote-value (object, i + 1)); end method; ///// WRAPPER-TO-CLASS // Given an instance of a wrapper, find the class and return it as // a . define method wrapper-to-class (ap :: , wrapper :: ) => (c :: , ok :: ) let (iclass, ok) = wrapper-to-iclass(ap, wrapper); if (ok) values(dylan-iclass-class(ap, iclass), #t) else values(as-remote-value(0), #f) end if end method; ///// WRAPPER-TO-ICLASS // Given an instance of a wrapper, find the implementation class, and // return a . define method wrapper-to-iclass (ap :: , wrapper :: ) => (c :: , ok :: ) read-instance-slot-element(ap, wrapper, 0) end method; ///// GET-METHOD-SPECIALIZERS // Given a (remote) instance of , return the vector of specializers // as a . define method get-method-specializers (ap :: , method-object :: ) => (s :: , ok :: ) let (siggy, ok) = read-instance-slot-element (ap, method-object, 1); if (ok) let (required-args, ok2) = read-instance-slot-element (ap, siggy, 1); if (ok2) values (required-args, #t) else values (as-remote-value(0), #f) end if else values (as-remote-value(0), #f) end if end method; ///// METHOD-IEP // Given an instance of , return the method's IEP // as a . define method method-iep (ap :: , method-object :: ) => (iep :: , ok :: ) read-instance-slot-element (ap, method-object, 3); end method; ///// METHOD-MEP // Given an instance of , return the method's MEP // as a . define method method-mep (ap :: , method-object :: ) => (iep :: , ok :: ) read-instance-slot-element (ap, method-object, 2); end method; ///// DYLAN-LAMBDA-XEP // Given an instance of a callable object, return the XEP // as a . define method dylan-lambda-xep (ap :: , lambda-object :: ) => (iep :: , ok :: ) read-instance-slot-element (ap, lambda-object, 0); end method; ///// GF-METHODS // Given a remote instance of , returns the vector // of methods as a define method gf-methods (ap :: , gf :: ) => (m :: , ok :: ) read-instance-slot-element (ap, gf, 4); end method; ///// DYLAN-INTEGER-DATA // Untag a dylan integer and return it as an actual define method dylan-integer-data (ap :: , integer-instance :: ) => (i :: ) tagged-remote-value-as-integer (integer-instance) end method; ///// DYLAN-CHARACTER-DATA // Untag a dylan character and return it as an actual define method dylan-character-data (ap :: , character-instance :: ) => (c :: ) tagged-remote-value-as-character (character-instance) end method; ///// DYLAN-MULTIDIMENSIONAL-ARRAY-SIZE // Given a instance, return its total // number of elements as an integer. define method dylan-multidimensional-array-size (ap :: , mda-instance :: ) => (i :: ) let (size, ok) = read-instance-slot-element(ap, mda-instance, 1); if (ok) tagged-remote-value-as-integer(size) else 0 end if end method; ///// DYLAN-MULTIDIMENSIONAL-ARRAY-DIMENSIONS // Given a instance, return its // dimensions. (Just returns a remote-value that points to // the sequence of dimensions. The caller needs to pick this apart). define method dylan-multidimensional-array-dimensions (ap :: , mda-instance :: ) => (vec :: ) let (vec, ok) = read-instance-slot-element(ap, mda-instance, 0); if (ok) vec else as-remote-value(0) end if end method; ///// DYLAN-MULTIDIMENSIONAL-ARRAY-ROW-MAJOR-ELEMENT // Given a instance, return the // nth row-major element of the array. define method dylan-multidimensional-array-row-major-element (ap :: , mda-instance :: , n :: ) => (data :: ) let (data, ok) = read-instance-slot-element(ap, mda-instance, 2 + n); if (ok) data else as-remote-value(0) end if end method; ///// DYLAN-LIMITED-ARRAY-SIZE // Given a instance, return its total // number of elements as an integer. define method dylan-limited-array-size (ap :: , mda-instance :: ) => (i :: ) let (size, ok) = read-instance-slot-element(ap, mda-instance, 2); if (ok) tagged-remote-value-as-integer(size) else 0 end if end method; ///// DYLAN-LIMITED-ARRAY-ELEMENT-TYPE // Given a simple-element-type-array instance, return its element-type. define method dylan-limited-array-element-type (ap :: , instance :: ) => (i :: ) let (slot, ok) = read-instance-slot-element(ap, instance, 0); if (ok) slot else as-remote-value(0) end if; end method; ///// DYLAN-LIMITED-ARRAY-DIMENSIONS // Given a instance, return its // dimensions. (Just returns a remote-value that points to // the sequence of dimensions. The caller needs to pick this apart). define method dylan-limited-array-dimensions (ap :: , mda-instance :: ) => (vec :: ) let (vec, ok) = read-instance-slot-element(ap, mda-instance, 1); if (ok) vec else as-remote-value(0) end if end method; ///// DYLAN-LIMITED-ARRAY-ROW-MAJOR-ELEMENT // Given a instance, return the // nth row-major element of the array. define method dylan-limited-array-row-major-element (ap :: , mda-instance :: , n :: ) => (data :: ) let (data, ok) = read-instance-slot-element(ap, mda-instance, 3 + n); if (ok) data else as-remote-value(0) end if end method; ///// DYLAN-VECTOR-SIZE // Given a simple-object-vector instance, return its size as an integer. define method dylan-vector-size (ap :: , sov-instance :: ) => (i :: ) let (size, ok) = read-instance-slot-element (ap, sov-instance, 0); if (ok) tagged-remote-value-as-integer(size); else 0; end if; end method; ///// DYLAN-LIMITED-VECTOR-SIZE // Given a simple-element-type-vector instance, return its size as an integer. define method dylan-limited-vector-size (ap :: , sov-instance :: ) => (i :: ) let (size, ok) = read-instance-slot-element (ap, sov-instance, 1); if (ok) tagged-remote-value-as-integer(size); else 0; end if; end method; ///// DYLAN-LIMITED-VECTOR-ELEMENT-TYPE // Given a simple-element-type-vector instance, return its element-type. define method dylan-limited-vector-element-type (ap :: , instance :: ) => (i :: ) let (slot, ok) = read-instance-slot-element(ap, instance, 0); if (ok) slot else as-remote-value(0) end if; end method; ///// DYLAN-TABLE-SIZE // Returns the number of entries in a table. // NB: This method is awfully aware of how the table data structure // is implemented, and knows the location of several slots. define method dylan-table-size (ap :: , table-instance :: ) => (i :: ) block () let tvec = read-instance-slot-element(ap, table-instance, 1); let additions = read-instance-slot-element(ap, tvec, 4); let deletions = read-instance-slot-element(ap, tvec, 6); let sz = tagged-remote-value-as-integer(additions) - tagged-remote-value-as-integer(deletions); sz exception() 0 end block end method; ///// DYLAN-VECTOR-ELEMENT // Given a simple-object-vector instance and an index, return the // appropriate vector element as a define method dylan-vector-element (ap :: , sov-instance :: , i :: ) => (v :: ) let (slot, ok) = read-instance-slot-element (ap, sov-instance, i + 1); if (ok) slot; else as-remote-value(0); end if end method; ///// DYLAN-LIMITED-VECTOR-ELEMENT // Given a simple-element-type-vector instance and an index, return the // appropriate vector element as a define method dylan-limited-vector-element (ap :: , sov-instance :: , i :: ) => (v :: ) let (slot, ok) = read-instance-slot-element (ap, sov-instance, i + 2); if (ok) slot; else as-remote-value(0); end if end method; ///// DYLAN-ENTRY-VECTOR-SIZE // Given an entry-vector instance, return its size as an integer. define method dylan-entry-vector-size (ap :: , sov-instance :: ) => (i :: ) let (size, ok) = read-instance-slot-element (ap, sov-instance, 1); if (ok) tagged-remote-value-as-integer(size); else 0; end if; end method; ///// DYLAN-ENTRY-VECTOR-ELEMENT // Given an entry-vector instance and an index, return the // appropriate vector element as a define method dylan-entry-vector-element (ap :: , sov-instance :: , i :: ) => (v :: ) let (slot, ok) = read-instance-slot-element (ap, sov-instance, i + 2); if (ok) slot; else as-remote-value(0); end if end method; ///// DYLAN-HEAD // Given an instance of a dylan pair, return the first element as a // define method dylan-head (ap :: , pair :: ) => (val :: ) let (hd, ok) = read-instance-slot-element (ap, pair, 0); if (ok) hd; else as-remote-value(0); end if end method; ///// DYLAN-TAIL // Given an instance of a dylan pair, return the second element as a // define method dylan-tail (ap :: , pair :: ) => (val :: ) let (tl, ok) = read-instance-slot-element (ap, pair, 1); if (ok) tl; else as-remote-value(0); end if end method; ///// DYLAN-ICLASS-CLASS // Given an implementation class instance, this returns the actual class // instance. define method dylan-iclass-class (ap :: , iclass-object :: ) => (val :: ) let (cls, ok) = read-instance-slot-element (ap, iclass-object, 1); // XX 1 if (ok) cls else as-remote-value(0) end if end method; /* ///// DYLAN-CLASS-DEBUG-NAME // Given an actual class instance, returns the debug name. This will // actually replicate the slot data, rather than returning the remote // value. define method dylan-class-debug-name (application :: , class-instance :: ) => (debug-name :: false-or()) let debug-name-data = read-instance-slot-element(application, class-instance, 1); let classification = classify-dylan-object(application, debug-name-data); if (classification == $boolean-false) #f else dylan-string-data(application, debug-name-data) end if end method; */ ///// DYLAN-CLASS-ICLASS // Given an actual class instance, returns its current implementation // class. define method dylan-class-iclass (ap :: , class-object :: ) => (val :: ) let (icls, ok) = read-instance-slot-element(ap, class-object, 2); if (ok) icls else as-remote-value(0) end if end method; ///// DYLAN-ICLASS-CLASS-STORAGE // Given a class instance, this returns the vector of class storage // spaces. define method dylan-iclass-class-storage (ap :: , iclass-object :: ) => (val :: ) let (spaces, ok) = read-instance-slot-element (ap, iclass-object, $iclass-class-storage-offset); if (ok) spaces; else as-remote-value(0); end if end method; ///// DYLAN-ICLASS-INSTANCE-SLOT-DESCRIPTORS // Given a class instance, this returns an instance which shoul be a simple- // object-vector of slot descriptors. define method dylan-iclass-instance-slot-descriptors (ap :: , iclass-object :: ) => (val :: ) let (descrs, ok) = read-instance-slot-element (ap, iclass-object, $iclass-instance-slot-descriptors-offset); if (ok) descrs; else as-remote-value(0); end if end method; ///// DYLAN-ICLASS-ALL-SLOT-DESCRIPTORS // Returns all slot descriptors associated with a class. define method dylan-iclass-all-slot-descriptors (ap :: , iclass-object :: ) => (val :: ) let (descrs, ok) = read-instance-slot-element (ap, iclass-object, $iclass-all-slot-descriptors-offset); if (ok) descrs; else as-remote-value(0); end if end method; ///// DYLAN-ICLASS-DIRECT-SLOT-DESCRIPTORS // Returns the descriptors for slots defined directly by this class // (ie, excluding inherited slots). define method dylan-iclass-direct-slot-descriptors (ap :: , iclass-object :: ) => (val :: ) let (descrs, ok) = read-instance-slot-element (ap, iclass-object, $iclass-direct-slot-descriptors-offset); if (ok) descrs; else as-remote-value(0); end if end method; ///// DYLAN-ICLASS-DIRECT-METHODS // Returns the direct methods on this class. define method dylan-iclass-direct-methods (ap :: , iclass-object :: ) => (val :: ) let (descrs, ok) = read-instance-slot-element (ap, iclass-object, $iclass-direct-methods-offset); if (ok) descrs; else as-remote-value(0); end if end method; ///// DYLAN-ICLASS-DIRECT-SUPERCLASSES // What a bloody strange name... // Given a class instance, this returns an instance which should be a // vector of direct superclasses. define method dylan-iclass-direct-superclasses (ap :: , iclass-object :: ) => (val :: ) let (sups, ok) = read-instance-slot-element (ap, iclass-object, $iclass-direct-superclasses-offset); if (ok) sups; else as-remote-value(0); end if end method; ///// DYLAN-ICLASS-ALL-SUPERCLASSES // Given a class instance, this returns an instance which should be a // sequence of superclasses define method dylan-iclass-all-superclasses (ap :: , iclass-object :: ) => (val :: ) let (sups, ok) = read-instance-slot-element (ap, iclass-object, $iclass-all-superclasses-offset); if (ok) sups; else as-remote-value(0); end if end method; ///// DYLAN-ICLASS-DIRECT-SUBCLASSES // Given a class instance, this returns an instance which should be a // sequence of subclasses define method dylan-iclass-direct-subclasses (ap :: , iclass-object :: ) => (val :: ) let (subs, ok) = read-instance-slot-element (ap, iclass-object, $iclass-direct-subclasses-offset); if (ok) subs; else as-remote-value(0); end if end method; ///// DYLAN-ICLASS-MM-WRAPPER // Given a class instance, this returns the wrapper that direct // instances of the class will posess. define method dylan-iclass-mm-wrapper (ap :: , iclass-object :: ) => (val :: ) let (wrapper, ok) = read-instance-slot-element (ap, iclass-object, $iclass-mm-wrapper-offset); if (ok) wrapper; else as-remote-value(0); end if end method; ///// DYLAN-ICLASS-REPEATED-SLOT-DESCRIPTOR // Given a class instance, returns the repeated slot descriptor. define method dylan-iclass-repeated-slot-descriptor (ap :: , iclass-object :: ) => (val :: ) let (descr, ok) = read-instance-slot-element (ap, iclass-object, $iclass-repeated-slot-descriptor); if (ok) descr; else as-remote-value(0); end if end method; /* ///// DYLAN-CLASS-INSTANCE-SLOT-DESCRIPTORS // Given a class instance, this returns an instance which shoul be a simple- // object-vector of slot descriptors. define method dylan-class-instance-slot-descriptors (ap :: , class-object :: ) => (val :: ) dylan-iclass-instance-slot-descriptors (ap, dylan-class-iclass(ap, class-object)) end method; ///// DYLAN-CLASS-ALL-SLOT-DESCRIPTORS // Returns all slot descriptors associated with a class. define method dylan-class-all-slot-descriptors (ap :: , class-object :: ) => (val :: ) dylan-iclass-all-slot-descriptors (ap, dylan-class-iclass(ap, class-object)) end method; ///// DYLAN-CLASS-DIRECT-SLOT-DESCRIPTORS // Returns the descriptors for slots defined directly by this class // (ie, excluding inherited slots). define method dylan-class-direct-slot-descriptors (ap :: , class-object :: ) => (val :: ) dylan-iclass-direct-slot-descriptors (ap, dylan-class-iclass(ap, class-object)) end method; ///// DYLAN-CLASS-DIRECT-METHODS // Returns the direct methods on this class. define method dylan-class-direct-methods (ap :: , class-object :: ) => (val :: ) dylan-iclass-direct-methods (ap, dylan-class-iclass(ap, class-object)) end method; ///// DYLAN-CLASS-DIRECT-SUPERCLASSES // What a bloody strange name... // Given a class instance, this returns an instance which should be a // vector of direct superclasses. define method dylan-class-direct-superclasses (ap :: , class-object :: ) => (val :: ) dylan-iclass-direct-superclasses (ap, dylan-class-iclass(ap, class-object)) end method; */ ///// DYLAN-CLASS-ALL-SUPERCLASSES // Given a class instance, this returns an instance which should be a // sequence of superclasses define method dylan-class-all-superclasses (ap :: , class-object :: ) => (val :: ) dylan-iclass-all-superclasses (ap, dylan-class-iclass(ap, class-object)) end method; /* ///// DYLAN-CLASS-DIRECT-SUBCLASSES // Given a class instance, this returns an instance which should be a // sequence of subclasses define method dylan-class-direct-subclasses (ap :: , class-object :: ) => (val :: ) dylan-iclass-direct-subclasses (ap, dylan-class-iclass(ap, class-object)) end method; */ ///// DYLAN-CLASS-MM-WRAPPER // Given a class instance, this returns the wrapper that direct // instances of the class will posess. define method dylan-class-mm-wrapper (ap :: , class-object :: ) => (val :: ) dylan-iclass-mm-wrapper (ap, dylan-class-iclass(ap, class-object)) end method; /* ///// DYLAN-CLASS-REPEATED-SLOT-DESCRIPTOR // Given a class instance, returns the repeated slot descriptor. define method dylan-class-repeated-slot-descriptor (ap :: , class-object :: ) => (val :: ) dylan-iclass-repeated-slot-descriptor (ap, dylan-class-iclass(ap, class-object)) end method; */ ///// DYLAN-SLOT-GETTER // Given a slot descriptor instance, returns the "getter" object, presumably // of type . define method dylan-slot-getter (ap :: , slot-descriptor :: ) => (getter-function :: ) let (getter, ok) = read-instance-slot-element (ap, slot-descriptor, 4); // XX 4 if (ok) getter; else as-remote-value(0); end if end method; ///// DYLAN-STRING-DATA // Given a instance, returns a local copy. define method dylan-string-data (ap :: , string-instance :: , #key clip-at = #f) => (val :: , clipped? :: ) let (size, ok) = read-instance-slot-element (ap, string-instance, 0); let size = tagged-remote-value-as-integer(size); let clipped? = #f; if (clip-at & (size > clip-at)) clipped? := #t; size := clip-at; end if; if (ok) values( read-byte-string (ap.debug-target-access-path, indexed-remote-value (string-instance, 2), size), clipped?) else values("", #f); end if; end method; ///// DYLAN-HANDLER-TYPE // Given a remote instance, returns a remote instance. define method dylan-handler-type (application :: , handler-instance :: ) => (type-instance :: ) let (type-val, ok) = read-instance-slot-element(application, handler-instance, 0); if (ok) type-val; else as-remote-value(0); end if end method; ///// DYLAN-DOUBLE-INTEGER-DATA // Given a remote object, return the high and low // words as . define method dylan-double-integer-data (application :: , instance :: ) => (data :: ) let (lo, oklo) = read-instance-slot-element(application, instance, 0); let (hi, okhi) = read-instance-slot-element(application, instance, 1); make(, high: hi, low: lo); end method; ///// DYLAN-HANDLER-FUNCTION // Given a remote instance, returns a remote instance. define method dylan-handler-function (application :: , handler-instance :: ) => (function-instance :: ) let (function-val, ok) = read-instance-slot-element(application, handler-instance, 1); if (ok) function-val; else as-remote-value(0); end if end method; ///// DYLAN-HANDLER-TEST // Given a remote instance, returns a remote instance. define method dylan-handler-test (application :: , handler-instance :: ) => (test-instance :: ) let (test-val, ok) = read-instance-slot-element(application, handler-instance, 2); if (ok) test-val; else as-remote-value(0); end if end method; ///// DYLAN-HANDLER-INIT-ARGUMENTS // Given a remote instance, returns a remote instance. define method dylan-handler-init-arguments (application :: , handler-instance :: ) => (vector-instance :: ) let (vector-val, ok) = read-instance-slot-element(application, handler-instance, 3); if (ok) vector-val; else as-remote-value(0); end if end method; ///// DYLAN-THREAD-NAME // Given a remote instance, returns the name of the thread // as a define method dylan-thread-name (application :: , thread-instance :: ) => (string-instance :: ) let (string-instance, ok) = read-instance-slot-element(application, thread-instance, 3); if (ok) string-instance; else as-remote-value(0); end if end method; ///// DYLAN-SIMPLE-CONDITION-FORMAT-STRING // Given a remote instance, returns a remote define method dylan-simple-condition-format-string (application :: , condition-instance :: ) => (string-instance :: ) let (string-val, ok) = read-instance-slot-element(application, condition-instance, 0); if (ok) string-val; else as-remote-value(0); end if; end method; ///// DYLAN-SIMPLE-CONDITION-FORMAT-ARGUMENTS // Given a remote instance, returns a remote define method dylan-simple-condition-format-arguments (application :: , condition-instance :: ) => (vector-instance :: ) let (vector-val, ok) = read-instance-slot-element(application, condition-instance, 1); if (ok) vector-val; else as-remote-value(0); end if; end method; ///// DYLAN-SINGLE-FLOAT-DATA // Given a single-float instance, returns a local copy. define method dylan-single-float-data (application :: , float-instance :: ) => (val :: ) let x :: = 0.0; let float-address = indexed-remote-value(float-instance, 1); block () x := read-single-float (application.debug-target-access-path, float-address); exception () x := 0.0; end block; x end method; ///// DYLAN-DOUBLE-FLOAT-DATA // Given a double-float instance, returns a local copy. define method dylan-double-float-data (application :: , float-instance :: ) => (val :: ) let x :: = as(, 0.0); let float-address = indexed-remote-value(float-instance, 1); block () x := read-double-float (application.debug-target-access-path, float-address); exception () x := as(, 0.0); end block; x end method; ///// DYLAN-OBJECT? // Returns #t if the supplied instance looks like a dylan object. // Strategy: If the object is tagged as an integer or character, then // it is a dylan object. Otherwise, it is treated as a pointer to // a dylan object, which should have a header pointing to a valid // wrapper... define method dylan-object? (ap :: , instance :: , #key address? :: ) => (val :: ) let tag = inspect-instance-tag(ap, instance); select (tag) $dylan-tag-boolean => if (ap.static-object-directory.booleans-tagged?) ~address? end; $dylan-tag-integer => ~address?; $dylan-tag-character => ~address?; $dylan-tag-pointer => let (w, w-ok) = read-instance-header(ap, instance); if (w-ok) let (ww, ww-ok) = read-instance-header(ap, w); if (ww-ok) let (www, www-ok) = read-instance-header(ap, ww); if (www-ok) ww = www & address-corresponds-to-primitive? (ap, ww, ap.wrapper-wrapper-primitive) end if end if end if; end select; end method; ///// INSTANCE-SYMBOLIC-NAME // Given any direct (but untagged) instance, this attempts to find a // name in the symbol table whose definition points to this object. define method dylan-instance-symbolic-name (ap :: , untagged-instance :: ) => (lib :: , mod :: , name :: , exact? :: ) let (closest, offset) = symbol-table-symbol-relative-address (ap.debug-target-symbol-table, untagged-instance); if (closest) let (lib, mod, name) = demangle-qualified-name(closest.remote-symbol-name); values(lib, mod, name, offset == 0); else values ("???", "???", "???"); end if end method; ///// DYLAN-SLOT-NAME // Given a corresponding to a dylan slot descriptor, returns // the name of the slot if it can be found. define method dylan-slot-name (ap :: , slot-descriptor :: ) => (name :: ) let (lib, mod, nm) = dylan-instance-symbolic-name (ap, dylan-slot-getter (ap, slot-descriptor)); nm; end method; ///// DYLAN-SYMBOL-NAME // Given a remote instance of , returns a remote instance of // naming the symbol. define method dylan-symbol-name (ap :: , sym :: ) => (name :: , ok :: ) read-instance-slot-element (ap, sym, 0); end method; ///// DYLAN-SINGLETON-OBJECT // Given a remote instance of , returns a remote instance of // that the singleton type represents. define method dylan-singleton-object (application :: , single :: ) => (remote-instance :: , ok :: ) read-instance-slot-element(application, single, 1); end method; ///// DYLAN-UNION-TYPE-FIRST-MEMBER // Given a remote instance of , returns a remote instance of the // first member type. define method dylan-union-type-first-member (application :: , union :: ) => (member-1 :: ) let (slot, ok) = read-instance-slot-element(application, union, 1); if (ok) slot else as-remote-value(0) end if end method; ///// DYLAN-UNION-TYPE-SECOND-MEMBER // Given a remote instance of , returns a remote instance of the // second member type. define method dylan-union-type-second-member (application :: , union :: ) => (member-2 :: ) let (slot, ok) = read-instance-slot-element(application, union, 2); if (ok) slot else as-remote-value(0) end if end method; ///// DYLAN-SUBCLASS-TYPE-CLASS // Given a remote instance of , returns a remote instance of // that the subclass type is referring to. define method dylan-subclass-type-class (application :: , subcltype :: ) => (clss :: ) let (slot, ok) = read-instance-slot-element(application, subcltype, 1); if (ok) slot else as-remote-value(0) end if end method; ///// DYLAN-MACHINE-WORD-DATA // Given a remote instance of , returns the // that holds it. define method dylan-machine-word-data (application :: , mw :: ) => (remote-word :: , ok :: ) read-instance-slot-element(application, mw, 0); end method; ///// DYLAN-STRETCHY-VECTOR-REPRESENTATION // Given a stretchy vector representation instance, returns the filled // size of the stretchy vector define method dylan-stretchy-vector-representation (ap :: , svec-instance :: ) => (rep :: ) let (rep, ok) = read-instance-slot-element (ap, svec-instance, 0); if (ok) rep; else as-remote-value(0); end if; end method; ///// DYLAN-STRETCHY-VECTOR-SIZE // Given a stretchy vector representation instance, returns the filled // size of the stretchy vector define method dylan-stretchy-vector-size (ap :: , svr-instance :: ) => (i :: ) let (size, ok) = read-instance-slot-element (ap, svr-instance, 0); if (ok) tagged-remote-value-as-integer(size); else 0; end if; end method; ///// DYLAN-STRETCHY-VECTOR-ELEMENT // Given a stretchy-vector-representation instance and an index, return the // appropriate vector element as a define method dylan-stretchy-vector-element (ap :: , svr-instance :: , i :: ) => (v :: ) let (slot, ok) = read-instance-slot-element (ap, svr-instance, i + 2); if (ok) slot; else as-remote-value(0); end if end method; ///// DYLAN-LIMITED-STRETCHY-VECTOR-REPRESENTATION // Given a stretchy element-type vector representation instance, returns the filled // size of the stretchy vector define method dylan-limited-stretchy-vector-representation (ap :: , svec-instance :: ) => (rep :: ) let (rep, ok) = read-instance-slot-element (ap, svec-instance, 1); if (ok) rep; else as-remote-value(0); end if; end method; ///// DYLAN-LIMITED-STRETCHY-VECTOR-SIZE // Given a stretchy vector representation instance, returns the filled // size of the stretchy vector define method dylan-limited-stretchy-vector-size (ap :: , svr-instance :: ) => (i :: ) let (size, ok) = read-instance-slot-element (ap, svr-instance, 0); if (ok) tagged-remote-value-as-integer(size); else 0; end if; end method; ///// DYLAN-LIMITED-STRETCHY-VECTOR-ELEMENT-TYPE // Given a stretchy-element-type-vector instance, return its element-type. define method dylan-limited-stretchy-vector-element-type (ap :: , instance :: ) => (i :: ) let (slot, ok) = read-instance-slot-element(ap, instance, 0); if (ok) slot else as-remote-value(0) end if; end method; ///// DYLAN-LIMITED-STRETCHY-VECTOR-ELEMENT // Given a stretchy-element-type-vector-representation instance and an index, // return the appropriate vector element as a define method dylan-limited-stretchy-vector-element (ap :: , svr-instance :: , i :: ) => (v :: ) let (slot, ok) = read-instance-slot-element (ap, svr-instance, i + 2); if (ok) slot; else as-remote-value(0); end if end method; ///// DYLAN-TABLE-VECTOR // Given a remote instance of , returns the appropriate // instance. define method dylan-table-vector (application :: , table-instance :: ) => (table-vector :: ) let (slot, ok) = read-instance-slot-element(application, table-instance, 1); if (ok) slot else as-remote-value(0); end if end method; ///// DYLAN-TABLE-KEYS-VECTOR // Given a remote instance of
, returns the vector instance that // holds the keys. define method dylan-table-keys-vector (application :: , table-instance :: ) => (keys-vector :: ) let table-vector = dylan-table-vector(application, table-instance); if (table-vector = as-remote-value(0)) table-vector else let (slot, ok) = read-instance-slot-element(application, table-vector, 8); if (ok) slot else as-remote-value(0) end if end if end method; ///// DYLAN-TABLE-VALUES-VECTOR // Given a remote instance of
, returns the vector instance that // holds the values. define method dylan-table-values-vector (application :: , table-instance :: ) => (keys-vector :: ) let table-vector = dylan-table-vector(application, table-instance); if (table-vector = as-remote-value(0)) table-vector else let (slot, ok) = read-instance-slot-element(application, table-vector, 9); if (ok) slot else as-remote-value(0) end if end if end method; ///// DYLAN-WRAPPER-PROPERTIES // Given any instance of , abstractify and return a // summary of information associated with the objects that it // wraps. define method dylan-wrapper-properties (application :: , wrapper :: ) => (fixed-slot-count :: , vector-scaling :: ) let version-word-address = indexed-remote-value(wrapper, 4); let field-word-address = indexed-remote-value(wrapper, 3); let field-word = read-value(application.debug-target-access-path, field-word-address); let version-word = read-value(application.debug-target-access-path, version-word-address); let fixed-slot-count = tagged-remote-value-as-integer(field-word); let vector-indicator = remote-value-low-order-bits(version-word, 3); let vector-scaling = if (vector-indicator == 7) 0 elseif ((vector-indicator == 4) | (vector-indicator == 5)) 1 else 4 end if; values(fixed-slot-count, vector-scaling); end method; ///// DYLAN-SIGNATURE-PROPERTIES // Given any instance of , abstractify and return the // properties. define method dylan-signature-properties (application :: , sig-instance :: ) => (number-required :: , number-values :: , rest? :: , keys? :: , all-keys? :: , default-rest? :: , default-values? :: ) let (slot, ok) = read-instance-slot-element(application, sig-instance, 0); if (ok) let properties-integer = truncate/(remote-value-low-order-bits(slot, 27), 4); let number-required = logand(properties-integer, #xff); let number-values = logand(truncate/(properties-integer, 256), #xff); let rest-bit = logand(properties-integer, #x40000); let keys-bit = logand(properties-integer, #x10000); let all-keys-bit = logand(properties-integer, #x20000); let default-rest-bit = logand(properties-integer, #x200000); let default-vals-bit = logand(properties-integer, #x400000); values(number-required, number-values, rest-bit > 0, keys-bit > 0, all-keys-bit > 0, default-rest-bit > 0, default-vals-bit > 0); else values(0, 0, #f, #f, #f, #f, #f) end if; end method; ///// DYLAN-SIGNATURE-REQUIRED // Given an instance of , return a corresponding // to the sequence of required parameters. define method dylan-signature-required (application :: , sig-instance :: ) => (req :: ) let (slot, ok) = read-instance-slot-element(application, sig-instance, 1); if (ok) slot else as-remote-value(0); end if; end method; ///// DYLAN-DEQUE-REPRESENTATION // Returns the implementation object from a deque instance. define method dylan-deque-representation (application :: , instance :: ) => (rep :: ) let (slot, ok) = read-instance-slot-element(application, instance, 1); if (ok) slot else as-remote-value(0) end if end method; ///// DYLAN-DEQUE-REPRESENTATION-PROPERTIES // Returns the first-index, last-index and current capacity of // an island-deque representation. define method dylan-deque-representation-properties (application :: , rep :: ) => (capacity :: , first :: , last :: ) let first-int = read-instance-slot-element(application, rep, 0); let last-int = read-instance-slot-element(application, rep, 1); let size-int = read-instance-slot-element(application, rep, 2); values (tagged-remote-value-as-integer(size-int), tagged-remote-value-as-integer(first-int), tagged-remote-value-as-integer(last-int)); end method; ///// DYLAN-DEQUE-SIZE // Returns the number of elements in a deque instance. define method dylan-deque-size (application :: , instance :: ) => (size :: ) let rep = dylan-deque-representation(application, instance); let (cap, first, last) = dylan-deque-representation-properties(application, rep); last - first + 1 end method; ///// DYLAN-DEQUE-ELEMENT // Returns an indexed element from a deque instance. define method dylan-deque-element (application :: , instance :: , i :: ) => (elt :: ) let rep = dylan-deque-representation(application, instance); let (cap, first, last) = dylan-deque-representation-properties(application, rep); let (el, ok) = read-instance-slot-element(application, rep, 3 + first + i); if (ok) el else as-remote-value(0) end if; end method; ///// DYLAN-SIGNATURE-VALUES // Given an instance of , return a corresponding // to the sequence of value types. define method dylan-signature-values (application :: , sig-instance :: ) => (vals :: ) let (slot, ok) = read-instance-slot-element(application, sig-instance, 2); if (ok) slot else as-remote-value(0); end if; end method; ///// DYLAN-KEYWORD-SIGNATURE-VALUES // Given an instance of , return a corresponding // to the sequence of value types. define method dylan-keyword-signature-values (application :: , sig-instance :: ) => (vals :: ) let (slot, ok) = read-instance-slot-element(application, sig-instance, 4); if (ok) slot else as-remote-value(0); end if; end method; ///// DYLAN-SIGNATURE-REST-VALUE // Given an instance of , return a corresponding // to #f, or the type of the #rest return value. define method dylan-signature-rest-value (application :: , sig-instance :: ) => (rst :: ) let (slot, ok) = read-instance-slot-element(application, sig-instance, 2); if (ok) slot else as-remote-value(0); end if; end method; define method dylan-value-signature-rest-value (application :: , sig-instance :: ) => (rst :: ) let (slot, ok) = read-instance-slot-element(application, sig-instance, 3); if (ok) slot else as-remote-value(0); end if; end method; define method dylan-keyword-signature-rest-value (application :: , sig-instance :: ) => (rst :: ) let (slot, ok) = read-instance-slot-element(application, sig-instance, 4); if (ok) slot else as-remote-value(0); end if; end method; define method dylan-value-keyword-signature-rest-value (application :: , sig-instance :: ) => (rst :: ) let (slot, ok) = read-instance-slot-element(application, sig-instance, 5); if (ok) slot else as-remote-value(0); end if; end method; ///// DYLAN-SIGNATURE-KEYS // Given an instance of , return a corresponding // to the sequence of keywords define method dylan-signature-keys (application :: , sig-instance :: ) => (kwds :: ) let (slot, ok) = read-instance-slot-element(application, sig-instance, 2); if (ok) slot else as-remote-value(0); end if; end method; ///// DYLAN-SIGNATURE-KEY-TYPES // Given an instance of , return a corresponding // to the sequence of keyword argument types. define method dylan-signature-key-types (application :: , sig-instance :: ) => (ktypes :: ) let (slot, ok) = read-instance-slot-element(application, sig-instance, 3); if (ok) slot else as-remote-value(0); end if; end method; ///// DYLAN-RANGE-START // Give a remote range instance, returns a for the number // at the start of the range. define method dylan-range-start (application :: , range-instance :: ) => (st :: ) let (slot, ok) = read-instance-slot-element(application, range-instance, 0); if (ok) slot else as-remote-value(0); end if end method; ///// DYLAN-RANGE-BY // Give a remote range instance, returns a for the number // at the step of the range. define method dylan-range-by (application :: , range-instance :: ) => (st :: ) let (slot, ok) = read-instance-slot-element(application, range-instance, 1); if (ok) slot else as-remote-value(0); end if end method; ///// DYLAN-RANGE-SIZE // Give a remote range instance, returns a for the number // at the size of the range. define method dylan-range-size (application :: , range-instance :: ) => (st :: ) let (slot, ok) = read-instance-slot-element(application, range-instance, 2); if (ok) slot else as-remote-value(0); end if end method; ///// DYLAN-SLOT-GETTER-FUNCTION // Given a remote slot descriptor, return the value for the getter // function. define method dylan-slot-getter-function (application :: , slot-instance :: ) => (val :: ) let (slot, ok) = read-instance-slot-element(application, slot-instance, 4); // XX 4 if (ok) slot else as-remote-value(0) end if end method; ///// DYLAN-SLOT-SETTER-FUNCTION // Given a remote slot descriptor, return the value for the setter // function. define method dylan-slot-setter-function (application :: , slot-instance :: ) => (val :: ) let (slot, ok) = read-instance-slot-element(application, slot-instance, 5); // XX 5 if (ok) slot else as-remote-value(0) end if end method; ///// DYLAN-SLOT-OWNER-CLASS // Given a remote slot descriptor, return the value for the class that // defines this slot. define method dylan-slot-owner-class (application :: , slot-instance :: ) => (val :: ) let (slot, ok) = read-instance-slot-element(application, slot-instance, 2); // XX 2 if (ok) slot else as-remote-value(0) end if end method; ///// DYLAN-SLOT-INIT-KEYWORD // Given a remote slot descriptor, return the value for the init keyword. define method dylan-slot-init-keyword (application :: , slot-instance :: ) => (val :: ) let (slot, ok) = read-instance-slot-element(application, slot-instance, 3); // XX 3 if (ok) slot else as-remote-value(0) end if end method; ///// DYLAN-SLOT-INIT-KEYWORD-REQUIRED // Given a remote slot descriptor, return the remote equivalent of either // #f or #t. define method dylan-slot-init-keyword-required (application :: , slot-instance :: ) => (val :: ) let (slot, ok) = read-instance-slot-element(application, slot-instance, 6); if (ok) slot else as-remote-value(0) end if end method; ///// DYLAN-SLOT-INIT-VALUE // A for the init-data in a slot, if it is known. define method dylan-slot-init-value (application :: , slot-instance :: ) => (val :: ) let (slot, ok) = read-instance-slot-element(application, slot-instance, 1); // XX 1 if (ok) slot else as-remote-value(0) end if end method; ///// DYLAN-SLOT-SPECIALIZER // Given a remote slot descriptor, return the value for the type that // this slot is specialized on. define method dylan-slot-specializer (application :: , slot-instance :: ) => (val :: ) let (slot, ok) = read-instance-slot-element(application, slot-instance, 6); // XX 6 if (ok) slot else as-remote-value(0) end if end method; ///// DYLAN-LAMBDA-SIGNATURE // Given a remote instance of any callable object, return a pointer to // the signature. define method dylan-lambda-signature (application :: , lambda-instance :: ) => (val :: ) let (slot, ok) = read-instance-slot-element(application, lambda-instance, 1); if (ok) slot else as-remote-value(0) end if end method; ///// DYLAN-METHOD-KEYWORD-SPECIFIERS // Returns a pointer to the sequence of keyword specifiers for a method. define method dylan-method-keyword-specifiers (application :: , method-instance :: ) => (val :: ) let (slot, ok) = read-instance-slot-element(application, method-instance, 4); if (ok) slot else as-remote-value(0) end if end method;