OT: Dynamic-CC, GC, Dynamic Types, and Prototype OO in C - C

This is a discussion on OT: Dynamic-CC, GC, Dynamic Types, and Prototype OO in C - C ; for my own dynamic C compiler effort, I have been specifying, and have already largely implemented, a mass of library functionality offering Garbage Collection (conservative), Dynamic Typing (through the "magically typed void pointer" approach), and a Prototype Object System (similar ...

+ Reply to Thread
Page 1 of 3 1 2 3 LastLast
Results 1 to 10 of 21

OT: Dynamic-CC, GC, Dynamic Types, and Prototype OO in C

  1. Default OT: Dynamic-CC, GC, Dynamic Types, and Prototype OO in C

    for my own dynamic C compiler effort, I have been specifying, and have
    already largely implemented, a mass of library functionality offering
    Garbage Collection (conservative), Dynamic Typing (through the "magically
    typed void pointer" approach), and a Prototype Object System (similar to
    that of Self or JavaScript).

    for general context (not intended as SPAM, but may come off this way I
    guess...):
    this is a C compiler which serves to behave more like a traditional VM or
    interpreter, namely in that it is capable of compiling and linking code into
    the running app at runtime. unlike a traditional VM, I am using C as the
    primary language (both for writing the implementation and for the scripts),
    and this VM is capable of linking against and directly using existing
    statically compiled/linked libraries (for example, stdio, OpenGL, the Win32
    API, ...).

    the goal is in part to have, in C, many of the capabilities traditionally
    available to languages such as LISP, Smalltalk, or Python, while still
    retaining the capabilities and raw performance of C (and hopefully
    eventually C++ as well, but a C++ compiler looks like a horrid beast to
    implement at present).

    at present, 32 bit windows is my primary development target.
    most of this is being developed under the LGPL.

    at present, the compiler still needs a little more work (buggy, incomplete,
    and non-standards-conformant in some places).

    well, LLVM is another project people can look into (for anyone that wants
    this kind of functionality, this project is a lot more usable at present).
    my effort is not intended to preclude the efforts of the LLVM folks, just
    doing my own thing mostly...


    as for the GC, Dynamic Types, and Prototype OO in C:

    in all this, the C language itself is left unaffected (this is library
    functionality, and does not involve use of custom compiler extensions). as
    such, it will not be the "nicest" possible option, but should be workable
    (basically, since I am stalling out on my ideas for implementing a scripting
    language based on my compiler core, I decided instead to implement all this
    as library functionality and stick to more or less "ordinary" C for the
    implementation/interface).

    neither the spec nor the library are "complete" at this point (I may specify
    a lot more than this, and at present have only implemented the GC and
    dynamic type system).

    I may also include the following other features in this framework:
    exceptions; multithreading; file-management/VFS, ...

    to a large degree, this is being derived from existing code of mine,
    however, in the process I am making fairly extensive modification to the
    code in which I am reusing (basically, I have about a 300 kloc existing
    codebase that I am mining for pieces in implementing all this). if taken
    "all the way", this will also include GL wrapping, a GL based GUI, 3D engine
    code, ... however, all this is more likely to undergo much more minor
    modification.

    basically, in all this, the dynamic C compiler is the core (however, it will
    not be a requirement for using any of this functionality).


    it is possible, however, that some people may find some of this
    "interesting".


    a few of the lib specs:
    ----

    GC Basics:
    This will be a conservative GC.
    Pointers may be freely stored on the stack, in global variables, or in other
    garbage-collected objects. The pointer may point anywhere within the
    allocated object.

    Caution needs to be excersized when mixing GC'ed data with non-GC'ed data
    (such as memory gained from malloc, mmap, ...). Likewise when "mutilating"
    pointers. In these cases, it is no longer required that the GC be able to
    correctly locate or identify these pointers (resulting in 'accidental'
    collection).


    GC API:
    void *gcalloc(size_t sz);
    void *gctalloc(char *type, size_t sz);

    void *gcatomic(size_t sz);
    void *gctatomic(char *type, size_t sz);

    void *gcrealloc(void *p, size_t sz);
    void *gcfree(void *p);
    char *gcgettype(void *p);
    int gctypep(void *p, char *ty);

    int gcsetfinal(char *ty, void (*fcn)(void *p));

    Uncertain Features:
    void *gctallocu(char *type, size_t sz); //unaligned alloc
    void *gcmalloc(size_t sz); //alloc initially-locked object
    void gclock(void *p); //prevent collection
    void gcunlock(void *p); //allow collection


    gcalloc():
    Allocates an object on the garbage-collected heap.
    The type of such a value will be viewed as being NULL.

    gctalloc():
    Allocates a typed object on the GC heap.
    The type is a string whose structure is not specified by the GC. For custom
    types, effort should be used to ensure that the string does not clash with a
    builtin type or one provided by another library.

    The creation of a new type may consist simply of allocating an object of the
    particular type.

    gcatomic()/gctatomic():
    Allocates an 'atomic' object on the garbage collected heap.
    An atomic object will differ from a normal object primarily in that the
    contents of an atomic object will not be scanned for references.
    As a result, it will be more suited for safely handling buffers and other
    types known not to contain memory references.

    gcrealloc():
    Reallocate an object to a larger or smaller size.
    The type will be be retained from the parent object.

    gcfree():
    Forcibly free an object. This should only be done when it is known that this
    object will no longer be accessed.

    gcgettype():
    Return the type associated with an object.
    If the pointer is not part of the GC's heap, or was gained from gcalloc,
    then the return value is NULL.

    gctypep():
    Returns a nonzero value if the type of p is the same as that given in ty.
    This determination will be based on string equality.

    gcsetfinal():
    Set the finalizer called for a specific type.
    This function will be called while freeing objects of this type.


    gcmalloc():
    If included, would create objects by default resembling those from malloc
    (assuming manual memory management, ...).

    However, unlike malloc(), the memory returned by gcmalloc() may be searched
    for pointers.


    ----

    Dynamic Type System:

    GC type names beginning with '_' will be reserved for the implementation.

    General Conventions:
    void *dy<type>(...);
    Will create an object of the type.

    int dy<type>p(void *p);
    Will return a nonzero value if p is the correct type.

    <type> dy<type>v(void *p);
    Will get the value for a specific type.

    char *dygettype(void *p);
    int dytypep(void *p, char *ty);
    Will get or check the type of an object.
    These will exist as there is no strict requirement that some of these
    builtin types will have the same GC type (or even necessarily be on-heap).
    In these cases, this function may need to do additional work in order to
    locate the correct type string.

    If only a single type needs to be checked, the provided specialized
    predicate functions will be viewed as the preferred means.


    Note:
    For Complex Types (such as arrays, conses, and hashes), it is acceptable to
    use any kind of pointer (it does not have to be from this type system, or
    necessarily even the GC). However, that is the intent that this be used
    mostly for dynamic types and GC'ed data, and other GC restrictions apply.


    Primitive Types: int; long; long long; float; double; fcomplex; dcomplex.
    Basic Types: string; wstring; symbol; keyword.
    Complex Types: array; cons; hash.

    ....

    so:
    void *dyint(int v);
    void *dylong(long v);
    void *dylonglong(long long v);
    void *dyfloat(float v);
    void *dydouble(double v);
    void *dyfcomplex(float _Complex v);
    void *dydcomplex(double _Complex v);

    char *dystring(char *s);
    char *dysymbol(char *s);
    char *dykeyword(char *s);
    wchar_t *dywstring(wchar_t *s);

    ....

    int dyintp(void *p);
    int dylongp(void *p);
    int dylonglongp(void *p);

    ....

    int dyintv(void *p);
    long dylongv(void *p);
    long long dylonglongv(void *p);

    ....


    Integer Type Disjointness
    It will not be required that integer types be disjoint.
    As a result, a value created with dyint() may still return a nonzero value
    with dylonglongp().

    Likewise, a value created by dylonglong() may be nonzero with dyintp() in
    the case where dylonglong() was called with a value sufficiently small to
    fit into an integer.

    As such, these predicates will mostly serve to indicate range requirements,
    rather than a strict type.

    Float and Double
    These will, however, be regarded as disjoint types.

    Real will exist as a psuedo type, which will be true for values decodable as
    a double.

    int dyrealp(void *p);
    double dyrealv(void *p);


    Arithmetic
    Functions will be provided for arithmetic on dynamic types.

    void *dyadd(void *a, void *b);
    void *dysub(void *a, void *b);
    void *dymul(void *a, void *b);
    void *dydiv(void *a, void *b);
    void *dymod(void *a, void *b);
    void *dyand(void *a, void *b);
    void *dyor(void *a, void *b);
    void *dyxor(void *a, void *b);

    void *dyneg(void *a);
    void *dynot(void *a);

    int dyeqp(void *a, void *b);
    int dyneqp(void *a, void *b);
    int dygtp(void *a, void *b);
    int dyltp(void *a, void *b);
    int dygep(void *a, void *b);
    int dylep(void *a, void *b);

    int dytruep(void *a);
    int dyfalsep(void *a);


    String:
    Will behave much the same as a GC'ed dynamicly typed strdup.
    Additionally, string merging may be performed, so the result should be
    regarded as immutable.

    Symbol and Keyword:
    These will be 2 different types, but each has essentially the same
    semantics.

    Beyond the different types, they will have another important property:
    Any 2 calls to the same function with the same input string produces the
    same output (allowing '==' to be used for equality checks).


    Array:

    void *dyarray(int cnt);
    Create an array with initially cnt pointers.

    void *dyarrayidx(void *p, int idx);
    void dyarraysetidx(void *p, int idx, void *q);
    Get and Set array index.

    void **dyarrayv(void *p);
    Get a 'void **' array representing the contents of the array.


    Cons:

    void *dycons(void *car, void *cdr);
    void *dycar(void *p);
    void *dycdr(void *p);

    void *dycaar(void *p);
    void *dycadr(void *p);
    void *dycdar(void *p);
    void *dycddr(void *p);
    (up to 4 levels).
    ....

    void *dylist1(void *a);
    void *dylist2(void *a, void *b);
    void *dylist3(void *a, void *b, void *c);
    void *dylist4(void *a, void *b, void *c, void *d);
    void *dylist5(void *a, void *b, void *c, void *d, void *e);
    void *dylist6(void *a, void *b, void *c, void *d, void *e, void *f);
    (up to 10).
    ....


    Hash:

    void *dyhash(int cnt);
    Create a hash with initially cnt slots in the table. Calling this with '0'
    will specify that the implementation use a default value.

    void *dyhashget(void *p, char *s);
    void *dyhashset(void *p, char *s, void *q);
    Get or Set the value associated with a given string index.
    Set will return the previous value (or NULL).

    The hash may be resized if it is full.


    ----

    Dynamically Typed Object Orientation

    Purpose:
    An dynamic object system is provided.
    This will provide a general prototype-based OO setup.
    The purpose will not to be "high performance", or to replace more
    traditional object systems or limit custom types/data, however, a goal will
    be that performance remain "acceptable" for many tasks.

    Objects will use a Prototype Object System.

    In this system, each object itself is viewed primarily as a bag of slots,
    with additional behaviors being gained by 'delegation'. In this system, a
    failure to locate a slot in a given object causes the slot to be looked up.
    Within this system, multiple delegates are allowed per-object (however,
    "parent" is the default). Additionally, the delegation graph will be allowed
    to be cyclic.

    Some calls may return a special value 'UNDEFINED', which will signal an
    error condition (unlike NULL, which simply means 'no value'). It will be
    considered invalid to use this value otherwise (this value is only returned,
    in error conditions, and is not to be passed around or stored). Later this
    value may also be used as a means of raising exceptions.

    When calling a method, a special method 'doesNotUnderstand' may be called
    prior to returning with an error condition. The 'doesNotUnderstand' method
    will be called with the same arguments as the original method call, but the
    args list will be prefixed with the method name.


    Conventions:
    DyOO will use a variant camelCase naming scheme.


    DyOO will have 2 major interfaces:

    Generating code to interface with existing dynamic types. This will be done
    by registering certain callbacks with the types. This will be intended
    mostly for types that are implemented in plain C (as structs, ...), but for
    whatever reason it is useful to be able to them access dynamically.

    A full prototype system, where methods are objects in themselves.

    For the former interface, these functions are provided.
    void dyTypeGetSlot(char *ty, dyt (*fcn)(dyt obj, dyt sym));
    void dyTypeSetSlot(char *ty, dyt (*fcn)(dyt obj, dyt sym, dyt val));
    void dyTypeNextSlot(char *ty, dyt (*fcn)(dyt obj, dyt sym));
    void dyTypeCallMethod(char *ty, dyt (*fcn)(dyt obj, dyt sym, dyt *args, int
    nargs));
    void dyTypeApply(char *ty, dyt (*fcn)(dyt obj, dyt *args, int nargs));


    For the latter interface:
    dyt dyFunc(dyt (*fcn)(dyt *args, int nargs));
    dyt dyMethod(dyt (*fcn)(dyt self, dyt *args, int nargs));
    Create a function or method.
    The primary difference between them will be the existence of the 'self'
    argument.

    Additional forms will be provided for functions with a fixed number of args:
    dyt dyFunc0(dyt (*fcn)());
    dyt dyFunc1(dyt (*fcn)(dyt));
    dyt dyFunc2(dyt (*fcn)(dyt, dyt));
    dyt dyFunc3(dyt (*fcn)(dyt, dyt, dyt));
    dyt dyFunc4(dyt (*fcn)(dyt, dyt, dyt, dyt));
    dyt dyFunc5(dyt (*fcn)(dyt, dyt, dyt, dyt, dyt));
    dyt dyFunc6(dyt (*fcn)(dyt, dyt, dyt, dyt, dyt, dyt));
    dyt dyFunc7(dyt (*fcn)(dyt, dyt, dyt, dyt, dyt, dyt, dyt));
    dyt dyFunc8(dyt (*fcn)(dyt, dyt, dyt, dyt, dyt, dyt, dyt, dyt));

    dyt dyMethod0(dyt (*fcn)(dyt self));
    dyt dyMethod1(dyt (*fcn)(dyt self, dyt a));
    dyt dyMethod2(dyt (*fcn)(dyt self, dyt a, dyt b));
    .... (up to 8)
    dyt dyMethodN(dyt (*fcn)(dyt self, dyt rest));
    dyt dyMethod1N(dyt (*fcn)(dyt self, dyt a, dyt rest));
    dyt dyMethod2N(dyt (*fcn)(dyt self, dyt a, dyt b, dyt rest));
    .... (up to 8)


    Objects:

    dyt dyObject();
    dyt dyObjectParent(dyt parent);
    Create a new prototype object. In the former case, the object is empty, and
    in the a latter, a parent is defined. The parent will be used in a 'parent'
    delegate slot.

    dyt dyGet(dyt obj, char *sym);
    Get a slot from an object.
    Returns UNDEFINED if the slot was not found.
    May recurse into delegates in order to locate the slot.

    void dySet(dyt obj, char *sym, dyt val);
    Set a slot in an object.
    Recursion may be used in order to locate the slot, and if found, it is set
    in the object in which it is defined. If not found, it is bound within the
    current object.

    void dyBind(dyt obj, char *sym, dyt val);
    This is similar to dySet(), but differs primarily in the way in which slots
    are assigned. In the case of dyBind, if the slot does not exist within the
    current object, it is created (rather than recursing and assigning).

    void dyBindMethod(dyt obj, char *sym, dyt mth);
    This will bind a method in the current object. This will behave differently
    than the normal 'set' or 'bind' operations, in that multiple versions of a
    method may be bound in an object. In this case, they will be merged into a
    kind of 'multi-method', which will dispatch based on args count. As such,
    Set() and Bind(), will not perform such merging (but will simply replace the
    method, including multi-methods).

    void dyDefMethod(dyt obj, char *sym,
    dyt (*fcn)(dyt self, dyt *args, int nargs));
    dyt dyDefMethod0(dyt obj, char *sym,
    dyt (*fcn)(dyt self));
    dyt dyDefMethod1(dyt obj, char *sym,
    dyt (*fcn)(dyt self, dyt a));
    dyt dyDefMethod2(dyt obj, char *sym,
    dyt (*fcn)(dyt self, dyt a, dyt b));
    .... (up to 8)

    void dyDefMethodN(dyt obj, char *sym,
    dyt (*fcn)(dyt self, dyt rest));
    dyt dyDefMethod1N(dyt obj, char *sym,
    dyt (*fcn)(dyt self, dyt a, dyt rest));
    dyt dyDefMethod2N(dyt obj, char *sym,
    dyt (*fcn)(dyt self, dyt a, dyt b, dyt rest));
    .... (up to 8)

    Define a method for an object.
    This will be similar to the above, but will accept a raw function pointer
    instead of a method object.

    The N-forms will fold the rest of the args into a list.


    dyt dyGetDelegate(dyt obj, char *sym);
    void dySetDelegate(dyt obj, char *sym, dyt val);
    Will get or set the value of an object's delegate.

    dyt dyGetParent(dyt obj);
    void dySetParent(dyt obj, dyt val);
    Special cases of the above, but are specialized to the 'parent' delegate.

    dyt dyCall(dyt obj, char *sym, dyt *args, int nargs);
    dyt dyCall0(dyt obj, char *sym);
    dyt dyCall1(dyt obj, char *sym, dyt a);
    dyt dyCall2(dyt obj, char *sym, dyt a, dyt b);
    .... (up to 8)
    dyt dyCallN(dyt obj, char *sym, dyt args);
    dyt dyCall1N(dyt obj, char *sym, dyt a, dyt args);
    dyt dyCall2N(dyt obj, char *sym, dyt a, dyt b, dyt args);
    .... (up to 8)


    Call a method within an object, and return the result.
    Returns UNDEFINED if the method was not found.
    Otherwise, this will return the return value of the method.


    A simple example:

    dyt testMath_doesNotUnderstand(dyt self, dyt sym, dyt rest)
    {
    if(!strcmp(sym, "pyth"))
    return(dysqrt(dyadd(
    dysqr(dycar(rest)),
    dysqr(dycadr(rest)))));
    return(NULL);
    }

    ....
    dyt obj, v;

    obj=dyObjectParent(dyTop());
    dySetDelegate(dyTop(), "testMath", obj);
    dyDefMethod1N(obj, "doesNotUnderstand", testMath_doesNotUnderstand);

    v=dyCall2(dyTop(), "pyth", dyint(3), dyint(4));



  2. Default Re: Dynamic-CC, GC, Dynamic Types, and Prototype OO in C


    "cr88192" <cr88192@nospam.hotmail.com> wrote in message
    news:bc34d$470c77d2$ca8010a3$6787@saipan.com...
    [...]

    > a few of the lib specs:
    > ----
    >
    > GC Basics:
    > This will be a conservative GC.
    > Pointers may be freely stored on the stack, in global variables, or in
    > other garbage-collected objects. The pointer may point anywhere within the
    > allocated object.


    [...]

    I hope that this is not a stop-the-world and/or collect-the-world scheme?


  3. Default Re: Dynamic-CC, GC, Dynamic Types, and Prototype OO in C

    "cr88192" <cr88192@nospam.hotmail.com> wrote in message
    news:bc34d$470c77d2$ca8010a3$6787@saipan.com...

    [...]

    Why does the Prototype OO need to be more complicated than the following
    technique:

    http://groups.google.com/group/comp....106926ba5db19f

    ?


  4. Default Re: Dynamic-CC, GC, Dynamic Types, and Prototype OO in C


    "Chris Thomasson" <cristom@comcast.net> wrote in message
    news:EuOdnblFktxJGpHanZ2dnUVZ_uCinZ2d@comcast.com...
    >
    > "cr88192" <cr88192@nospam.hotmail.com> wrote in message
    > news:bc34d$470c77d2$ca8010a3$6787@saipan.com...
    > [...]
    >
    >> a few of the lib specs:
    >> ----
    >>
    >> GC Basics:
    >> This will be a conservative GC.
    >> Pointers may be freely stored on the stack, in global variables, or in
    >> other garbage-collected objects. The pointer may point anywhere within
    >> the allocated object.

    >
    > [...]
    >
    > I hope that this is not a stop-the-world and/or collect-the-world scheme?


    sadly, at present, it is...

    however, I have it to be able to collect a 1GB heap in about 400ms on my
    current main computer (Athlon 64 X2 4400+). it is a bit slower (about 10s)
    if I fill the heap with random garbage, but this is outside its "reasonable"
    operating range (a smaller heap is much faster).

    however, my intention is to fix this when I get to it (when I implement
    threading...).


    I had written an incremental collector at one point in the past (2002 or
    2003), but the main project in which I had been using this particular
    collector (only slightly modified since about 2004, until recently), I have
    been using single-threaded development (back then I had decided
    multithreading was too much hassle and too error prone to be worthwhile).

    but, now, I have been looking into implementing write barriers, ...

    however, before this point, I had considered a half-assed approach:
    I use SuspendThread for all the GC-managed threads on starting GC, and
    ResumeThread on them when the collector finishes...

    (worst case option: it would be possible to use Boehm in the background, and
    simply dump the whole dynamic typesystem on top of Boehm...).


    sad but, yeah...



  5. Default Re: Dynamic-CC, GC, Dynamic Types, and Prototype OO in C


    "Chris Thomasson" <cristom@comcast.net> wrote in message
    news:b4SdncAjsaMVFJHanZ2dnUVZ_vmlnZ2d@comcast.com...
    > "cr88192" <cr88192@nospam.hotmail.com> wrote in message
    > news:bc34d$470c77d2$ca8010a3$6787@saipan.com...
    >
    > [...]
    >
    > Why does the Prototype OO need to be more complicated than the following
    > technique:
    >
    > http://groups.google.com/group/comp....106926ba5db19f
    >
    > ?


    this Prototype OO is also Dynamically Typed...

    the kind of informal OO mentioned in the referenced thread, is not
    ammendable to really any kind of dynamic behavior.

    now, more "manual" methods are still considered reasonable in my effort,
    they are just handled a little differently...


    ok, I have written several script VMs in the past, and the design I have
    used, is based largely on the way I typically approach implementing
    Prototype OO in a script VM...

    the extra API complexity (all the variations for differing numbers and
    configurations of arguments) is due to trying to make the interface more
    usable from C code (getting a flat array or a list as the sole source of
    function/method arguments, is, lame...).


    the extra complexity in the 'call' variations is for a similar reason.

    dyCall2(obj, "foo", bar, baz);
    is slightly less cumbersome than:
    dyCall(obj, "foo", dylist2(bar, baz));

    and so on...


    likewise, I may well have some intention of implementing global
    object/method hashing (where the object and method name are used to
    hash-optimize method lookups), and this requires a lot of what I have here.

    I will argue what I have, for what it is worth, is likely to pay for
    itself...

    or such...



  6. Default Re: Dynamic-CC, GC, Dynamic Types, and Prototype OO in C

    ["Followup-To:" header set to comp.lang.misc.]
    On 2007-10-10, cr88192 <cr88192@nospam.hotmail.com> wrote:
    >> I hope that this is not a stop-the-world and/or collect-the-world scheme?

    >
    > sadly, at present, it is...


    > however, I have it to be able to collect a 1GB heap in about 400ms on my
    > current main computer (Athlon 64 X2 4400+). it is a bit slower (about 10s)
    > if I fill the heap with random garbage, but this is outside its "reasonable"
    > operating range (a smaller heap is much faster).


    (I'd say the number of heap objects, and the way they are connected (the avg
    distance from a root) would be the rate determinating factor, not the heap total size))


  7. Default OT: Incremental GC (was Re: Dynamic-CC, GC, Dynamic Types, and Prototype OO in C)


    "Chris Thomasson" <cristom@comcast.net> wrote in message
    news:EuOdnblFktxJGpHanZ2dnUVZ_uCinZ2d@comcast.com...
    >
    > "cr88192" <cr88192@nospam.hotmail.com> wrote in message
    > news:bc34d$470c77d2$ca8010a3$6787@saipan.com...
    > [...]
    >
    >> a few of the lib specs:
    >> ----
    >>
    >> GC Basics:
    >> This will be a conservative GC.
    >> Pointers may be freely stored on the stack, in global variables, or in
    >> other garbage-collected objects. The pointer may point anywhere within
    >> the allocated object.

    >
    > [...]
    >
    > I hope that this is not a stop-the-world and/or collect-the-world scheme?


    digging around the Win32 API, I have found that windows has built-in support
    for write barriers.
    this is, pretty damn useful...

    it is actually seemingly nicer than the mmap/mprotect approach (no signal
    catching, ...).


    so, yeah, in my MM/GC, I will probably go and implement write barriers, and
    probably go and try to make the thing thread safe.
    as such, will also make it into an incremental collector, which may or may
    not involve drastic restructuring. not like this has not already been done
    in this (modifying it to support 'large objects' and make use of a
    marking-stack were hardly minor either...).


    of course, going from malloc to VirtualAlloc, may require some alteration to
    the large object allocator (namely, the implementation of yet another
    specialized memory manager). since it will need to do a lot of memory-object
    queries, I may not implement a traditional block and free-list allocator,
    but maybe base the allocator on AVL trees (combining AVL trees and
    allocation of fragmentary underlying memory could be difficult though,
    unless each major chunk had a semi-disjoint tree).

    alternatively, I could use virtual alloc as an allocator directly
    (questionable).
    or, implement a good old block and free-list allocator (downsides: various
    sized free lists, and the need to merge adjacent blocks on freeing).
    another possibility is the implementation of a much larger cell allocator
    (each cell being 256 bytes, or maybe 1kB, or even a full page...).


    AVL trees:
    pros: allow very fast pointer/memory lookups; adjacency queries; ...
    cons: given the absence of free lists, the options amount to either a linear
    best fit, or first fit (best fit is O(n log2 n));
    memory lookups are unlikely to be the limiting factor in this case (already
    done in the 'large object' GC code).

    Direct VirtualAlloc:
    pros: simple.
    cons: 4kB alloc granularity, likely to do bad things to the address space.

    Blocks and Free Lists:
    pros: can look up reasonably well-sized memory blocks fairly quickly
    (depends, but O(1) is reasonable);
    cons: the need to explicitly split and merge memory blocks; absent
    additional structures, memory object lookups are an O(n) operation (may be
    acceptable, since these will only occure during the sweep phase).

    Large Cells:
    pros: fast lookups, no need for explicit merging when freeing;
    cons: cell-based chunking; need to search for free memory; memory allocation
    is almost always first-fit.


    it looks like, in this case, and the usage pattern (as the back end
    allocator/freer for the large-object part of the GC), the blocks and
    free-list approach is probably the best option.


    well, I will see how much time I have (I have other stuff that needs to be
    done as well, groan...).



  8. Default Re: Incremental GC (was Re: Dynamic-CC, GC, Dynamic Types, and Prototype OO in C)

    "cr88192" <cr88192@nospam.hotmail.com> wrote in message
    news:daf8b$470ea2fa$ca8010a3$9298@saipan.com...
    >
    > "Chris Thomasson" <cristom@comcast.net> wrote in message
    > news:EuOdnblFktxJGpHanZ2dnUVZ_uCinZ2d@comcast.com...
    >>
    >> "cr88192" <cr88192@nospam.hotmail.com> wrote in message
    >> news:bc34d$470c77d2$ca8010a3$6787@saipan.com...
    >> [...]
    >>
    >>> a few of the lib specs:
    >>> ----
    >>>
    >>> GC Basics:
    >>> This will be a conservative GC.

    [...]
    >> I hope that this is not a stop-the-world and/or collect-the-world scheme?

    >
    > digging around the Win32 API, I have found that windows has built-in
    > support for write barriers.
    > this is, pretty damn useful...

    [...]
    > so, yeah, in my MM/GC, I will probably go and implement write barriers,
    > and probably go and try to make the thing thread safe.
    > as such, will also make it into an incremental collector, which may or may
    > not involve drastic restructuring.

    [...]
    > of course, going from malloc to VirtualAlloc, may require some alteration
    > to the large object allocator (namely, the implementation of yet another
    > specialized memory manager).

    [...]

    There are some advantages to using VirtualAlloc in the context of an
    alignment trick using in lock/wait-free programming:

    http://groups.google.ca/group/comp.p...0d09027a9dd9e2

    http://groups.google.ca/group/comp.p...b6d6fc3de1c5c3

    http://groups.google.com/group/comp....573a4efc77608d



    Also IMHO, you simply HAVE to read all of the following:

    http://groups.google.com/group/comp....b2736484af3ca6

    http://blogs.sun.com/dave/resource/A...ronization.txt

    http://www.trl.ibm.com/people/kawati...chiya05phd.pdf
    (chapter 6)

    http://appcore.home.comcast.net/vzoom/round-1.pdf
    (page 3/section 3)

    http://appcore.home.comcast.net/vzoom/round-2.pdf
    (page 2/section 1.2)

    https://coolthreads.dev.java.net/ser...essageID=11068
    (lock-free reader pattern...)

    http://en.wikipedia.org/wiki/Read-copy-update
    (classic RCU...)


    Follow the links at the end of the following post as well:

    https://coolthreads.dev.java.net/ser...1&forumID=1797


    Also, (in a C++ context):

    http://groups.google.com/group/comp....007ffdf246d50e

    http://groups.google.com/group/comp....a5a3f804c84ea4

    http://groups.google.com/group/comp....d7fcd780dc467c



    All of that information can be of service wrt "low-overhead" scaleable
    multi-threading.


  9. Default Re: Incremental GC (was Re: Dynamic-CC, GC, Dynamic Types, and Prototype OO in C)

    [...]

    > http://appcore.home.comcast.net/vzoom/round-1.pdf
    > (page 3/section 3)
    >
    > http://appcore.home.comcast.net/vzoom/round-2.pdf
    > (page 2/section 1.2)


    [...]

    These were drafts. Sorry for any typos in there. For the scope of this
    discussion, I would focus on page 3/section 3 of round-1... The logic is
    correct wrt the given scenario.


  10. Default Re: Incremental GC (was Re: Dynamic-CC, GC, Dynamic Types, and Prototype OO in C)

    "Chris Thomasson" <cristom@comcast.net> wrote in message
    news:7NmdnY7dhYIilpLanZ2dnUVZ_rCtnZ2d@comcast.com...
    > [...]
    >
    >> http://appcore.home.comcast.net/vzoom/round-1.pdf
    >> (page 3/section 3)
    >>
    >> http://appcore.home.comcast.net/vzoom/round-2.pdf
    >> (page 2/section 1.2)

    >
    > [...]
    >
    > These were drafts. Sorry for any typos in there. For the scope of this
    > discussion, I would focus on page 3/section 3 of round-1... The logic is
    > correct wrt the given scenario.


    Ahh shit!

    I should not of linked to the pre-alpha one. Acutally, there is a logic
    error concerining the following paragraph:


    Bugged paragraph:
    __________________________________________________
    Lets briefly compare the per-node solution to a lock-free reader pattern
    using the distributed proxy reference counting algorithm. Now the reader
    threads could setup a dynamic ratio of searches to synchronization
    operations. Lets say the programmer created a synchronization schedule that
    allowed for reader threads to execute only 1 synchronization operation for
    every, lets say, thousand searches. How does that compare with the per-node
    locking scheme that can expose threads to possibly hundreds of lock/unlock
    operations per-search? Well, by the time a reader thread in the per-node
    locking setup finally completes a thousand searches with an average of
    six-hundred lock/unlock operations per-search, it will have executed
    approximately sixhundred thousand atomic operations and six-hundred thousand
    StoreLoad style memory barriers. When a reader thread in the lock-free
    reader pattern completes a thousand searches it will have only executed
    four, or less, atomic operations and/or StoreLoad style memory barriers. It
    can boil down to an average of twelve-million versus four, or less,
    expensive operations perthread, per-thousand-searches. In my option, the
    choice is clear: The lock-free reader pattern is a winner.
    __________________________________________________


    The above paragraph says that 1000 lock-based searches, with an average of
    600 lock and unlock's per-search is only 600,000 atomic-ops and 600,000
    membars... Well, that is simply NOT true. Since a single lock or unlock
    operation usually takes 1 atomic-op and 1 membar; the figure '600,000'
    should really be '1,200,000'."


    So, the following statement is correct:

    A 1000 lock-based searches, with an average of 600 lock/unlock per-search is
    usually 1,200,000 atomic ops and 1,200,000 membars, for a total of 2,400,000
    operations per-1000-lock-based-searches.




    This means that the following statement:

    "It can boil down to an average of twelve-million versus four, or less,
    expensive operations per-thread, per-thousand-searches."


    is wrong. Here is the fix:

    It can boil down to an average of 2,400,000 expensive operations per-1000
    searches when using lock-based, versus four, or less, expensive operations
    using vZOOM for the same load.



    Sorry!


+ Reply to Thread
Page 1 of 3 1 2 3 LastLast

Similar Threads

  1. ORM tool for dynamic types
    By Application Development in forum CSharp
    Replies: 0
    Last Post: 10-14-2007, 09:40 AM
  2. Static, dynamic and Lisp types.
    By Application Development in forum lisp
    Replies: 7
    Last Post: 09-30-2007, 03:08 PM
  3. deserializing types defined in dynamic assemblies
    By Application Development in forum DOTNET
    Replies: 1
    Last Post: 09-28-2005, 08:53 AM
  4. Question about Static and Dynamic Types in Java
    By Application Development in forum Java
    Replies: 2
    Last Post: 02-14-2005, 12:01 AM
  5. Restricted access to dynamic types in Visual Studio .NET 2003 SP1
    By Application Development in forum DOTNET
    Replies: 0
    Last Post: 01-10-2005, 08:47 AM