www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - minimal object.d implementation that allows classes

reply =?UTF-8?B?THXDrXM=?= Marques <luis luismarques.eu> writes:
Is there a small druntime/object.d implementation that allows 
basic support for classes, without bringing the whole druntime 
implementation with it?
Dec 06 2017
next sibling parent reply Eugene Wissner <belka caraus.de> writes:
On Wednesday, 6 December 2017 at 17:17:40 UTC, Luís Marques wrote:
 Is there a small druntime/object.d implementation that allows 
 basic support for classes, without bringing the whole druntime 
 implementation with it?
http://arsdnet.net/dcode/minimal.zip ?
Dec 06 2017
parent reply =?UTF-8?B?THXDrXM=?= Marques <luis luismarques.eu> writes:
On Wednesday, 6 December 2017 at 17:52:16 UTC, Eugene Wissner 
wrote:
 http://arsdnet.net/dcode/minimal.zip ?
I tried that one, but I was having trouble getting it to work (it seems to have bit rotten), and it does much more than I need, which probably is adding to the work to fix it.
Dec 06 2017
parent Adam D. Ruppe <destructionator gmail.com> writes:
On Wednesday, 6 December 2017 at 18:32:11 UTC, Luís Marques wrote:
 On Wednesday, 6 December 2017 at 17:52:16 UTC, Eugene Wissner 
 wrote:
 http://arsdnet.net/dcode/minimal.zip ?
I tried that one, but I was having trouble getting it to work (it seems to have bit rotten), and it does much more than I need, which probably is adding to the work to fix it.
Yeah, minimal.zip is getting a bit old, but most the changes should be fairly small - adjusting sizes mainly. I just haven't done that for a year or two. The basic process is compile and link, if something doesn't work, copy/paste enough in to make the error go away. Sizes can be gotten from real druntime with __traits(classInstanceSize) and such, then you put in a dummy buffer to pad to it (remembering the vptr and monitor already get tou part of the way there). minimal.zip does a bit more than the bare minimum, but polymorphic classes DO require a fair chunk of code - various typeinfo and cast functions, some kind of memory function - and some of that code requires other code like struct typeinfo too (ugh, but the compiler insists). minimal.zip also includes exceptions and some startup stuff but that's mostly just because such were easy after polymorphism worked so I did because I can. Of course, if targetting webassembly, you can prolly cut all that out and rely on the javascript plumbing instead (i think). Certainly the asm functions will need to be cut there.
Dec 07 2017
prev sibling next sibling parent Timo Sintonen <t.sintonen luukku.com> writes:
On Wednesday, 6 December 2017 at 17:17:40 UTC, Luís Marques wrote:
 Is there a small druntime/object.d implementation that allows 
 basic support for classes, without bringing the whole druntime 
 implementation with it?
https://bitbucket.org/timosi/minlibd This is mainly targeted to microcontrollers which do not have any operating system. If this is not suitable for you, at least there are lists of needed files and required changes. It might be possible to reduce this further but I have not yet had need for that. Feel free to ask more info if you are interested.
Dec 06 2017
prev sibling next sibling parent reply Wild <xwildn00bx gmail.com> writes:
On Wednesday, 6 December 2017 at 17:17:40 UTC, Luís Marques wrote:
 Is there a small druntime/object.d implementation that allows 
 basic support for classes, without bringing the whole druntime 
 implementation with it?
You could modify the one I use for PowerNex[1]. It is a hacked version of Adam D. Ruppes minimal.zip. There are only a few imports for strlen, mem{set,move,cpy}, etc. You probably need to add some sort of entrypoint and maybe implement a few more runtime functions. - Dan [1] https://github.com/PowerNex/PowerNex/blob/master/loader/src/object.d
Dec 07 2017
parent reply =?UTF-8?B?THXDrXM=?= Marques <luis luismarques.eu> writes:
On Thursday, 7 December 2017 at 08:59:08 UTC, Wild wrote:
 You could modify the one I use for PowerNex[1]. It is a hacked 
 version of Adam D. Ruppes
 minimal.zip. There are only a few imports for strlen, 
 mem{set,move,cpy}, etc.
This one seems to be the one for me. For instance, typeid(ClassName) seems to work, which I need. For completeness, I had looked into minlibd but it didn't seemed compatible with LDC and difficult for me to fix, IIRC. Regarding Mike's question of what my use case is, I wanted my program to run in webassembly/asmjs. Since druntime/phobos haven't been ported to that target, I was being careful with my design to not depend on the runtime, but then I found out I love the openmethods package. So I decided to check if I could implement just enough of druntime to allow a forked version of openmethods to work. As far as I can tell that's feasible.
Dec 07 2017
parent reply Jean-Louis Leroy <jl leroy.nyc> writes:
On Thursday, 7 December 2017 at 13:08:09 UTC, Luís Marques wrote:
 On Thursday, 7 December 2017 at 08:59:08 UTC, Wild wrote:
 You could modify the one I use for PowerNex[1]. It is a hacked 
 version of Adam D. Ruppes
 minimal.zip. There are only a few imports for strlen, 
 mem{set,move,cpy}, etc.
This one seems to be the one for me. For instance, typeid(ClassName) seems to work, which I need. For completeness, I had looked into minlibd but it didn't seemed compatible with LDC and difficult for me to fix, IIRC. Regarding Mike's question of what my use case is, I wanted my program to run in webassembly/asmjs. Since druntime/phobos haven't been ported to that target, I was being careful with my design to not depend on the runtime, but then I found out I love the openmethods package. So I decided to check if I could implement just enough of druntime to allow a forked version of openmethods to work. As far as I can tell that's feasible.
I am currently trying to understand how the compiler and the runtime interact. ClassInfo contains a vtbl array whose ptr property is the same as the vptr found in an instance of that class. However, when I modify that pointer (e.g. by reserving 1000 more entries) and create a new instance, it still contains the old pointer. So it looks like the compiler sets the vptr without consulting the ClassInfo but somehow reflects it there. I'd appreciate if anybody can explain how it works, or sends me links to relevant info. Example: import std.stdio; class Foo { void foo() {} } void main() { auto oldPtr = Foo.classinfo.vtbl.ptr; Foo.classinfo.vtbl.reserve(1000); writeln(oldPtr != Foo.classinfo.vtbl.ptr); // true Object foo = new Foo(); writeln(oldPtr == *cast(void***)foo); // true, alas } ...at least that's what I get with dmd.
Dec 07 2017
parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
On 12/7/17 9:45 AM, Jean-Louis Leroy wrote:
 On Thursday, 7 December 2017 at 13:08:09 UTC, Luís Marques wrote:
 On Thursday, 7 December 2017 at 08:59:08 UTC, Wild wrote:
 You could modify the one I use for PowerNex[1]. It is a hacked 
 version of Adam D. Ruppes
 minimal.zip. There are only a few imports for strlen, 
 mem{set,move,cpy}, etc.
This one seems to be the one for me. For instance, typeid(ClassName) seems to work, which I need. For completeness, I had looked into minlibd but it didn't seemed compatible with LDC and difficult for me to fix, IIRC. Regarding Mike's question of what my use case is, I wanted my program to run in webassembly/asmjs. Since druntime/phobos haven't been ported to that target, I was being careful with my design to not depend on the runtime, but then I found out I love the openmethods package. So I decided to check if I could implement just enough of druntime to allow a forked version of openmethods to work. As far as I can  tell that's feasible.
I am currently trying to understand how the compiler and the runtime interact. ClassInfo contains a vtbl array whose ptr property is the same as the vptr found in an instance of that class. However, when I modify that pointer (e.g. by reserving 1000 more entries) and create a new instance, it still contains the old pointer. So it looks like the compiler sets the vptr without consulting the ClassInfo but somehow reflects it there. I'd appreciate if anybody can explain how it works, or sends me links to relevant info. Example: import std.stdio; class Foo {   void foo() {} } void main() {   auto oldPtr = Foo.classinfo.vtbl.ptr;   Foo.classinfo.vtbl.reserve(1000);   writeln(oldPtr != Foo.classinfo.vtbl.ptr); // true   Object foo = new Foo();   writeln(oldPtr == *cast(void***)foo); // true, alas }
The object is constructed here: https://github.com/dlang/druntime/blob/master/src/rt/lifetime.d#L71 specifically, the vtbl is set when you blit the initializer array (another piece of the TypeInfo) into the class object here: https://github.com/dlang/druntime/blob/master/src/rt/lifetime.d#L115 So basically, the reason why it happens is because the pointer you are changing is not the piece that actually is used to intialize the block. On a side note however, you really shouldn't change data in a ClassInfo at all, and probably the compiler shouldn't let you! This is static readonly data, and changing this is I think even disallowed on some OSes. Relevant source of how vtbls in D work: https://dlang.org/spec/abi.html#classes -Steve
Dec 07 2017
parent reply Jean-Louis Leroy <jl leroy.nyc> writes:
On Thursday, 7 December 2017 at 14:59:57 UTC, Steven 
Schveighoffer wrote:
 The object is constructed here: [...]
Thanks for the pointers, you've saved me a lot of time :)
 On a side note however, you really shouldn't change data in a 
 ClassInfo at all, and probably the compiler shouldn't let you!
This experiment is related to an ongoing discussion with Walter, Andrei and Ali on extending D with general mechanisms to better support libraries like openmethods. I will post in Studies soon.
Dec 07 2017
next sibling parent reply Jean-Louis Leroy <jl leroy.nyc> writes:
On Thursday, 7 December 2017 at 15:09:45 UTC, Jean-Louis Leroy 
wrote:
 On Thursday, 7 December 2017 at 14:59:57 UTC, Steven 
 Schveighoffer wrote:
 The object is constructed here: [...]
Thanks for the pointers, you've saved me a lot of time :)
 On a side note however, you really shouldn't change data in a 
 ClassInfo at all, and probably the compiler shouldn't let you!
This experiment is related to an ongoing discussion with Walter, Andrei and Ali on extending D with general mechanisms to better support libraries like openmethods. I will post in Studies soon.
Cool: import std.stdio; class Foo { abstract void report(); } class Bar : Foo { override void report() { writeln("I'm fine!"); } } void main() { auto oldPtr = Bar.classinfo.vtbl.ptr; Bar.classinfo.vtbl.reserve(1000); Bar.classinfo.vtbl.ptr[Bar.classinfo.vtbl.length] = cast(void*) 0x123456; writeln(oldPtr != Bar.classinfo.vtbl.ptr); // true *cast(void***) Bar.classinfo.m_init.ptr = Bar.classinfo.vtbl.ptr; Foo foo = new Bar(); writeln(oldPtr == *cast(void***)foo); // false foo.report(); // I'm fine! writeln((*cast(void***)foo)[Bar.classinfo.vtbl.length]); // 123456 }
Dec 07 2017
parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
On 12/7/17 10:21 AM, Jean-Louis Leroy wrote:
 Bar.classinfo.vtbl.ptr[Bar.classinfo.vtbl.length] = cast(void*) 0x123456;
This is a buffer overflow, why are you doing this specifically? -Steve
Dec 07 2017
parent reply Jean-Louis Leroy <jl leroy.nyc> writes:
On Thursday, 7 December 2017 at 15:34:09 UTC, Steven 
Schveighoffer wrote:
 On 12/7/17 10:21 AM, Jean-Louis Leroy wrote:
 Bar.classinfo.vtbl.ptr[Bar.classinfo.vtbl.length] = 
 cast(void*) 0x123456;
This is a buffer overflow, why are you doing this specifically? -Steve
It's not an overflow because of the call to `reserve`. It is part of an experiment related to supporting user-defined per-class metadata by extending the vtable.
Dec 07 2017
parent Steven Schveighoffer <schveiguy yahoo.com> writes:
On 12/7/17 10:45 AM, Jean-Louis Leroy wrote:
 On Thursday, 7 December 2017 at 15:34:09 UTC, Steven Schveighoffer wrote:
 On 12/7/17 10:21 AM, Jean-Louis Leroy wrote:
 Bar.classinfo.vtbl.ptr[Bar.classinfo.vtbl.length] = cast(void*) 
 0x123456;
This is a buffer overflow, why are you doing this specifically? -Steve
It's not an overflow because of the call to `reserve`. It is part of an experiment related to supporting user-defined per-class metadata by extending the vtable.
Ah, ok. Take care, I'm not sure that the classinfo instances are scanned by the GC. Might be better to use C malloc. -Steve
Dec 07 2017
prev sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2017-12-07 16:09, Jean-Louis Leroy wrote:

 This experiment is related to an ongoing discussion with Walter, Andrei 
 and Ali on extending D with general mechanisms to better support 
 libraries like openmethods. I will post in Studies soon.
Modifying the vtable can be useful for mocking and stubbing methods as well. -- /Jacob Carlborg
Dec 08 2017
parent Jean-Louis Leroy <jl leroy.nyc> writes:
On Friday, 8 December 2017 at 14:59:12 UTC, Jacob Carlborg wrote:
 On 2017-12-07 16:09, Jean-Louis Leroy wrote:

 This experiment is related to an ongoing discussion with 
 Walter, Andrei and Ali on extending D with general mechanisms 
 to better support libraries like openmethods. I will post in 
 Studies soon.
Modifying the vtable can be useful for mocking and stubbing methods as well.
Indeed. The initial vtable is in read only memory, but the re-allocated one is writeable.
Dec 08 2017
prev sibling parent Mike Franklin <slavo5150 yahoo.com> writes:
On Wednesday, 6 December 2017 at 17:17:40 UTC, Luís Marques wrote:
 Is there a small druntime/object.d implementation that allows 
 basic support for classes, without bringing the whole druntime 
 implementation with it?
I can get away with just this (https://github.com/JinShil/stm32f42_discovery_demo/blob/master/sour e/runtime/object.d) in GDC. It will likely cause LDC to crash (See https://github.com/ldc-developers/ldc/issues/781, https://github.com/ldc-developers/ldc/issues/552). I haven't tested it with DMD. But, I'm not really using classes in the typical way. Instead, I'm more-or-less using them as namespaces with static polymorphism. For an example, see https://github.com/JinShil/stm32f42_discovery_demo/blob/master/source/stm32f42/pwr.d What you need in object.d will likely depend on how you intend to use your classes. What's your use case? Mike
Dec 07 2017