Module: dood Synopsis: The Dylan object-oriented database Author: Jonathan Bachrach 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 //define constant $unbound-proxy-value = list("UNBOUND PROXY"); define open dood-class () // weak slot dood-proxy-value, // init-value: $unbound-proxy-value, init-keyword: object:; end dood-class; define inline method lookup-proxy (dood :: , object) => (false-or-proxy) element(dood-disk-objects(dood), object, default: #f); end method; define inline method maybe-lookup-proxy (dood :: , object) => (false-or-proxy) unless (dood-batch-mode?(dood)) lookup-proxy(dood, object) end unless; end method; define method dood-clean-proxies (dood :: ) => () dood-proxies(dood) := make(); remove-all-keys!(dood-disk-objects(dood)); end method; define method install-proxy (dood :: , object, proxy :: ) dood-disk-objects(dood)[object] := proxy; unless (dood-batch-mode?(dood)) dood-proxies(dood) := add!(dood-proxies(dood), object); // dood-proxy-value(proxy) := object; end unless; end method; define method install-read-proxy (dood :: , object, proxy :: ) unless (dood-batch-mode?(dood)) install-proxy(dood, object, proxy) end unless; end method; define inline function dood-as-proxy (dood :: , object, make-proxy :: , #rest arguments) => (proxy :: ) // if (dood-batch-mode?(dood)) maybe-lookup-proxy(dood, object) | begin let proxy = apply(make-proxy, dood, object, arguments); install-proxy(dood, object, proxy); proxy end // else // apply(make-proxy, dood, object, arguments) // end if end function; define open generic dood-restore-proxy (dood :: , proxy :: ) => (memory-object); define open generic dood-disk-object-default (dood :: , object) => (disk-object); define method dood-disk-object-default (dood :: , object) => (disk-object) object end method; define method dood-disk-object (dood :: , object) => (disk-object) dood-disk-object-default(dood, object); end method; define method dood-disk-object (dood :: , object :: ) => (object) /* let external-dood = object-dood(object); if (external-dood & external-dood ~== dood) // SANITY CHECK if (dood-name(external-dood) == dood-name(dood)) // break("DIRT FOUND IN DOOD %=", object); object-dood(object) := dood; // dood-pointer(object) := #f; object else dood-as-proxy(dood, object, dood-make-cross-proxy, external-dood) end if else object end if */ object end method; define method read-object-using-class-at (dood :: , class :: subclass(), address ::
) => (object) let object = dood-read-object-of-at(dood, class, address); let value = dood-restore-proxy(dood, object); install-read-proxy(dood, value, object); dood-format("REREGISTERING PROXY\n"); dood-register-read-object(dood, value, address); // dood-proxy-value(object) := value; value end method; //// BINDINGS define open class () constant slot dood-proxy-library-name, required-init-keyword: library:; constant slot dood-proxy-module-name, required-init-keyword: module:; end class; define open class () constant slot dood-proxy-module, required-init-keyword: module:; constant slot dood-proxy-variable-name, required-init-keyword: variable:; end class; define function dood-as-program-module-proxy (dood :: , library-name, module-name) => (proxy :: ) let library-name = library-name & as(, library-name); let module-name = as(, module-name); let proxies = dood-module-proxies(dood); let proxies :: = element(proxies, library-name, default: #f) | (element(proxies, library-name) := make()); element(proxies, module-name, default: #f) | (element(proxies, module-name) := make(, module: module-name, library: library-name)) end function; define function dood-make-program-binding-proxy (dood :: , object) => (proxy :: ) let (variable, module, library) = locate-variable(object); if (~variable) error("Couldn't locate program variable for %=", object); end; make(, variable: variable, module: dood-as-program-module-proxy(dood, library, module)) end function; define method dood-disk-object (dood :: , object :: ) => (proxy :: ) dood-as-proxy(dood, object, dood-make-program-binding-proxy) end method; define method dood-disk-object (dood :: , object :: ) => (proxy :: ) error("NON GENERIC-FUNCTIONS ARE UNSUPPORTED IN DOOD"); end method; define method dood-restore-proxy (dood :: , proxy :: ) => (object) proxy end method; define method dood-restore-proxy (dood :: , proxy :: ) => (object) let mod-proxy = dood-proxy-module(proxy); variable-value (dood-proxy-variable-name(proxy), dood-proxy-module-name(mod-proxy), dood-proxy-library-name(mod-proxy)); end method; // define constant // = ; // define constant dood-make-class-program-binding-proxy // = dood-make-program-binding-proxy; // define method dood-disk-object // (dood :: , object :: ) // => (proxy :: ) // dood-as-proxy(dood, object, dood-make-program-binding-proxy) // end method; define class () end class; define function dood-make-class-program-binding-proxy (dood :: , object :: ) => (proxy :: ) let (variable, module, library) = locate-variable(object); // TODO: BOOTSTRAPPING let (variable, module, library) = if (variable) values(variable, module, library) else class->variable(object); end if; if (~variable) error("Couldn't locate program variable for %=", object); end; make(, variable: variable, module: dood-as-program-module-proxy(dood, library, module)) end function; define method dood-disk-object (dood :: , object :: ) => (proxy :: ) dood-as-proxy(dood, object, dood-make-class-program-binding-proxy) end method; define method dood-restore-proxy (dood :: , proxy :: ) => (object :: ) let mod-proxy = dood-proxy-module(proxy); local method booted-lookup () variable->class (as(, dood-proxy-variable-name(proxy)), as(, dood-proxy-module-name(mod-proxy)), as(, dood-proxy-library-name(mod-proxy))); end method, method boot-lookup () variable-value (dood-proxy-variable-name(proxy), dood-proxy-module-name(mod-proxy), dood-proxy-library-name(mod-proxy)); end method; block () boot-lookup() | booted-lookup(); // TODO: BOOTSTRAPPING exception () booted-lookup(); end block; end method; /// /// SLOT-VALUE /// define primary class () constant slot proxy-address :: false-or(
) = #f, init-keyword: address:; end class; define class () end class; define class () constant slot proxy-slot-descriptor :: , required-init-keyword: slot-descriptor:; end class; /* define constant $fixed-slot-value-proxy-classes :: = make(); define macro fixed-offset-slot-value-proxy-definer { define fixed-offset-slot-value-proxy ?:name ?offset:expression } => { define class "" () keyword slot-descriptor:; end class; define method proxy-slot-descriptor (proxy :: "") => (res :: ) ?offset end method; // HACK: EMULATOR HACK size($fixed-slot-value-proxy-classes) := ?offset + 1; element($fixed-slot-value-proxy-classes, ?offset) := "" } end macro; define fixed-offset-slot-value-proxy proxy-0 0; define fixed-offset-slot-value-proxy proxy-1 1; define fixed-offset-slot-value-proxy proxy-2 2; define fixed-offset-slot-value-proxy proxy-3 3; define fixed-offset-slot-value-proxy proxy-4 4; define fixed-offset-slot-value-proxy proxy-5 5; define fixed-offset-slot-value-proxy proxy-6 6; define fixed-offset-slot-value-proxy proxy-7 7; define fixed-offset-slot-value-proxy proxy-8 8; define fixed-offset-slot-value-proxy proxy-9 9; define fixed-offset-slot-value-proxy proxy-10 10; define fixed-offset-slot-value-proxy proxy-11 11; define fixed-offset-slot-value-proxy proxy-12 12; define fixed-offset-slot-value-proxy proxy-13 13; define fixed-offset-slot-value-proxy proxy-14 14; define fixed-offset-slot-value-proxy proxy-15 15; define fixed-offset-slot-value-proxy proxy-16 16; define fixed-offset-slot-value-proxy proxy-17 17; define fixed-offset-slot-value-proxy proxy-18 18; define fixed-offset-slot-value-proxy proxy-19 19; define fixed-offset-slot-value-proxy proxy-20 20; define fixed-offset-slot-value-proxy proxy-21 21; define fixed-offset-slot-value-proxy proxy-22 22; define fixed-offset-slot-value-proxy proxy-23 23; define fixed-offset-slot-value-proxy proxy-24 24; define fixed-offset-slot-value-proxy proxy-25 25; define fixed-offset-slot-value-proxy proxy-26 26; define fixed-offset-slot-value-proxy proxy-27 27; define fixed-offset-slot-value-proxy proxy-28 28; define fixed-offset-slot-value-proxy proxy-29 29; */ define inline method lookup-slot-value-proxy-class (slotd :: ) => (res :: ) // if (slotd >= size($fixed-slot-value-proxy-classes)) // else // element($fixed-slot-value-proxy-classes, slotd) // end if; end method; define inline method make-slot-value-proxy (dood :: , address ::
, disk-offset :: , slot-descriptor :: ) => (res :: ) make(lookup-slot-value-proxy-class(slot-descriptor), dood: dood, address: address, slot-descriptor: slot-descriptor) end method; define sealed domain object-dood (); define sealed domain object-dood-setter (, ); define sealed domain initialize (); define sealed domain make (subclass()); define inline function lazy-value? (object) => (well? :: ) instance?(object, ) end function; define constant dood-lazy-value? = lazy-value?; /* define constant $slot-value-proxies = make(); define method make-slot-value-proxy (disk-offset :: , slot-descriptor :: ) => (res :: ) let proxies :: = element($slot-value-proxies, disk-offset, default: #f) | (element($slot-value-proxies, disk-offset) := make()); element(proxies, slot-descriptor, default: #f) | (element(proxies, slot-descriptor) := make(, slot-offset: disk-offset, slot-descriptor: slot-descriptor)); end method; */ define method make-address-proxy (dood :: , address ::
, disk-offset :: ) => (res :: ) make(, dood: dood, address: address + disk-offset + 1) end method; define function dood-force-address-proxy (x :: ) => (res) let state :: = object-dood-state(x); let dood :: = dood-dood-state(state); with-dood-state (dood, state) let address = proxy-address(x); with-saved-position (dood) read-object-at(dood, address); end with-saved-position end with-dood-state; end function; define function dood-force-slot-value-proxy (x :: ) => (res) let state :: = object-dood-state(x); let dood :: = dood-dood-state(state); with-dood-state (dood, state) let address = proxy-address(x); with-saved-position (dood) read-pointer(dood, address); end with-saved-position end with-dood-state; end function; define inline function dood-maybe-force-address-proxy (x) => (value, forced? :: ) if (lazy-value?(x)) values(dood-force-address-proxy(x), #t) else values(x, #f) end if end function; define inline function dood-maybe-force-slot-value-proxy (x) => (value, forced? :: ) if (lazy-value?(x)) values(dood-force-slot-value-proxy(x), #t) else values(x, #f) end if end function; define variable *trace-allocation?* = #f; define inline function dood-force-lazy-slot-value-proxy (object, x) => (res) if (lazy-value?(x)) if (*trace-allocation?*) let slotds = slot-descriptors(object-class(object)); depth-format-out("FORCING %= %=\n", object-class(object), slot-getter(element(slotds, proxy-slot-descriptor(x)))); *print-depth* := *print-depth* + 1; end if; let value = dood-force-slot-value-proxy(x); dood-slot-value(object, proxy-slot-descriptor(x)) := value; if (*trace-allocation?*) *print-depth* := *print-depth* - 1; end if; value else x end if end function; define inline function dood-lazy-slot-value (object, getter :: ) dood-force-lazy-slot-value-proxy(object, getter(object)) end function; define inline function dood-force-disk-slot-value-proxy (object, x) => (res) if (lazy-value?(x)) dood-force-slot-value-proxy(x) else x end if end function; define inline function dood-disk-slot-value (object, getter :: ) dood-force-disk-slot-value-proxy(object, getter(object)); end function; //// CROSS DOOD define open class () constant slot dood-proxy-dood-name, required-init-keyword: dood-name:; end class; define open generic dood-make-cross-proxy (dood :: , object, external-dood :: ) => (object); //// WRAPPER PROXY define open dood-class () constant slot dood-wrapper-proxy-object, required-init-keyword: object:; // @@@@ REMOVE ME @@@@ weak constant slot dood-wrapper-proxy-object-address = #f; end dood-class; define method walk-slots (dood :: , info :: , proxy :: ) let object = dood-wrapper-proxy-object(proxy); let predefined-address = element(dood-predefine-addresses(dood), object, default: #f); // HACK: SHOULDN'T REALLOCATE let address ::
= predefined-address | dood-allocate-instance(dood, object); next-method(); // WRITE OVER WRAPPED OBJECT SLOT WITH REAL OBJECT if (walk-info-commit?(info)) let proxy-address ::
= dood-walked-address(dood, proxy); dood-write-at(dood, tag-as-address(object, address), proxy-address + 1); end if; // WALK REAL OBJECT unless (predefined-address) walk-object(dood, info, object, address); end unless; end method; define method read-object-using-class-at (dood :: , class :: subclass(), address ::
) => (object) dood-forwarding-address(dood) := address; with-saved-position (dood) let object = read-object(dood); end with-saved-position; let proxy = next-method(); proxy end method; // eof