Re: [RfC] constant PMCs and classes
Leopold Toetsch wrote: We currently have constant Key and Sub PMCs both created from the packfile at load time. They live in the constant_table pointing to a constant PMC pool. But we need more. We have allover the core code like this: string_from_cstring(interpreter, pIt, 0) Don't do that. Instead, do: string_from_cstring(interpreter, pIt, PObj_external_FLAG); This will allow parrot to avoid making a copy of pIt. Actually, IMHO, we should disallow (both for this, and for string_make) a simple default of 0 for 'flags'. Instead, I think we should require that the programmer explicitly indicate exactly what the pointer we're passing in is. It could be any of: A buffer which might be reused by something else, so we should allocate space, and copy the data into it. A const static buffer which won't (can't) ever change. We can capture it and use it, but shouldn't [ever] try altering it. An external buffer which won't change on us, but which is not constant memory ... like non-const static memory, or perhaps a string from a program in which parrot is embedded. We can freely use it (without copying it) and even change it, but growing it requires that we allocate from our own arenas. Also, when we no longer need it, just let go of it. A buffer allocated by mem_sys_allocate, which the calling function wants to *give up* to the string. We can use it directly without copying it, reallocate it as needed, and free it to our memory arenas when we're done with it. Indeed, by indicating this, it would now be the string's responsibility to free up the memory when it's gone, instead of being the caller's responsibility. If there are any other scenarios, I'm not aware of them. The majority of calls from user-written C code will be of type 2: A constant static buffer which won't (can't) ever change (like in your example). Some user-land code will be type 1 (for example, turning the result of inet_ntoa into a string). I'm not sure if type 3 has a use -- one can claim that the string is type 1, without harm. There wouldn't be too many times that type 4 would need to be used, except as an optomization (change places where we make a STRING then free the memory that the cstring was in, into making a STRING and giving up ownership of the cstring-pointer to the STRING). As I recall, there are places in perl5 where buffers are stolen instead of copied... this would be the same sort of thing. Strings whose buffers are of type 2 would have a big advantage with respect to COW: nothing needs to be done to make them COW (we copy the pointer, and copy the flags), and nothing needs to be done to make them non-COW. In addition, I think we need *another* argument: One to tell what type of STRING* object we want back. In particular, we might want back a constant one, for which appending or truncating is illegal. In addition to that, we might (or might not) be willing to accept a STRING which isn't newly allocated, but was cached from an earlier call. key = key_new_cstring(interpreter, _message); IMHO, key_new_cstring should allow a flags argument, so that we can pass in either a PObj_external_FLAG or 0; otherwise, it won't know whether or not it needs to make a copy. to create some STRINGs or entries in hashes. The keys should be constant PMCs and they should be shared as well as the STRINGs. We need this in objects.c (\0\0anonymous), for setting standard property names internally and for the current hash based implementation of Exceptions. This leads to my proposal: * const_string_from_cstring - return cached constant string or create one Instead of a new entry point, how about adding whatever behavior you want here to be an added behavior of string_from_cstring, dependent on what flags were passed as a third argument? * const_key_new_cstring - return cached PMC or create a constant PMC If * constant_pmc_new* - ditto (called from above) Further we would need for some classes a Const$Class variant, where the set-like vtables throw an exception. These classes should be autogenerated from *.pmc for all classes that have a const_too or such in their classes $flags. This leads to changes in parsing the vtable.tbl - which we need anyway to do the proposed var/value split of vtables. e.g. [FETCH] get_integer ... [STORE] set_integer ... [PUSH] push_integer ... and so on. The section names conform (where applicable) to methods described in Tie::*(3pm). -- $a=24;split//,240513;s/\B/ = /for@@=qw(ac ab bc ba cb ca );{push(@b,$a),($a-=6)^=1 for 2..$a/6x--$|;print [EMAIL PROTECTED] ]\n;((6=($a-=6))?$a+=$_[$a%6]-$a%6:($a=pop @b))redo;}
Re: [RfC] constant PMCs and classes
Juergen Boemmels wrote: Leopold Toetsch [EMAIL PROTECTED] writes: Benjamin Goldberg [EMAIL PROTECTED] wrote: #define PARROT_DECLARE_STATIC_STRING(name, cstring) \ [ big snip ] While Juergen's original or your proposal are fine, they don't work (or not as proposed). First there are compiler issues: [snip] The declaration looks ok at first sight, my gcc 2.95.2 might be wrong, but anyway, a bigger problem is here: PIO_printf(interpreter, %S\n, mystr); Program received signal SIGSEGV, Segmentation fault. 0x400f8725 in make_COW_reference (interpreter=0x8049828, s=0x80486e0) at string.c:95 95 PObj_constant_CLEAR(s); (gdb) bac #0 0x400f8725 in make_COW_reference (interpreter=0x8049828, s=0x80486e0) at string.c:95 #1 0x400f91b6 in string_copy (interpreter=0x8049828, s=0x80486e0) at string.c:497 Ah it seems that make_COW_reference wants to change a constant string. As my code puts the static strings in .rodata (this was one of the targets of my experiments) it is not possible in any way to change this item. The problem is that as far as the COW logic knows, only the *buffer* is constant. In this (peciliar?) case, both the string buffer and the string header are constant. I even think PObj_constant_CLEAR(s) is evil. One reason for setting a PObj_constant_FLAG is to declare that an object will not change. Unsetting this flag means breaking this contract. It's clearing the constant flag, then making the copy, then turning the constant flag back on. If it were only the buffer that were in const memory, and not the header, this would be perfectly fine. I think. snippet from objdump: .rodata0011 _Parrot_static_mystr_cstring.15 .rodata0024 _Parrot_static_mystr_STRING.16 If we get a general compiler independend solution for declaring static STRINGs we still have nothing for static keys. The main problem of all this code is the union initialiser. Static keys could also created with an initialisier, but i think this needs an other union-val to be initialized. There are gcc extension to init arbitary members, but ANSI-C allows only the initializiation of the first member. -- $a=24;split//,240513;s/\B/ = /for@@=qw(ac ab bc ba cb ca );{push(@b,$a),($a-=6)^=1 for 2..$a/6x--$|;print [EMAIL PROTECTED] ]\n;((6=($a-=6))?$a+=$_[$a%6]-$a%6:($a=pop @b))redo;}
Re: [RfC] constant PMCs and classes
can people please test, if the program below compiles cleanly now: It doesn't. MSVC++ aint' happy when * is at back of a name. static const char PCONCAT(name,_cstring) * = cstring; this static const char *PCONCAT(name,_cstring) = cstring; would be okay.
Re: [RfC] constant PMCs and classes
The issues WRT the union initializer are gone now (can people please test, if the program below compiles cleanly now) - but: - make_COW_* sets flag on the source string [1] - if that is solved (with a special RO flag, or whatever) we have: - string_make sets a default type and encoding if these arguments were NULL. These constant strings have NULL for encoding/type so during string_append as the encodings differ transcode is called - next SIGSEGV with NULL encoding pointer. So using these .rodata-constant STRINGs needs a lot of work. - COW code (there are problems with COWed stacks anyway) - transcoding stuff (should be changed to use {strstart, byteidx} and do something about default vs NULL type/encoding. leo [1] this was called via string_copy in the spf_vtable code (I don't see the point, why a string should be copied just to print it - removed) #include parrot/parrot.h #include parrot/embed.h #if ! DISABLE_GC_DEBUG # define GC_DEBUG_VERSION ,0 #else # define GC_DEBUG_VERSION #endif #define PCONCAT(b,c) _Parrot_static_##b##c #define PARROT_DECLARE_STATIC_STRING(name, cstring) \ static const char PCONCAT(name,_cstring) * = cstring; \ static const struct parrot_string_t \ PCONCAT(name,_STRING) = { \ { /* pobj_t */ \ {{ \ (void*)PCONCAT(name,_cstring), \ sizeof(PCONCAT(name,_cstring)) \ }}, \ PObj_constant_FLAG \ GC_DEBUG_VERSION \ }, \ sizeof(PCONCAT(name,_cstring)), \ (void*)PCONCAT(name,_cstring), \ sizeof(PCONCAT(name,_cstring)) - 1, \ NULL, \ NULL, \ 0 \ }, * const name = PCONCAT(name,_STRING) int main(int argc, char* argv[]) { int dummy_var; struct Parrot_Interp * interpreter; PARROT_DECLARE_STATIC_STRING(mystr, some string here); interpreter = Parrot_new(); Parrot_init(interpreter, (void*) dummy_var); PIO_printf(interpreter, %S\n, mystr); return 0; }
Re: [RfC] constant PMCs and classes
Leopold Toetsch [EMAIL PROTECTED] writes: The issues WRT the union initializer are gone now (can people please test, if the program below compiles cleanly now) - but: - make_COW_* sets flag on the source string [1] - if that is solved (with a special RO flag, or whatever) we have: - string_make sets a default type and encoding if these arguments were NULL. These constant strings have NULL for encoding/type so during string_append as the encodings differ transcode is called - next SIGSEGV with NULL encoding pointer. It is in principle possible to use a default_encoding in the static initialiser, but then a relocation is needed because the static string and default_encoding are not in the same object-file. This would lead to a longer load-time. On the other hand accessing the encoding through macros #define ENCODING_skip_forward(enc, p, n) ((enc) ? \ (enc)-skip_forward(p, n) : \ default_enc-skip_forward(p, n)) has a runtime cost; the test will fool the branch prediction. So using these .rodata-constant STRINGs needs a lot of work. - COW code (there are problems with COWed stacks anyway) - transcoding stuff (should be changed to use {strstart, byteidx} and do something about default vs NULL type/encoding. Next idea: create a new function STRING *string_from_static_cstring(const char *cstr); which does not copy the string to newly allocated memory. But maybe then the problems with COW are still there. [...] bye boe -- Juergen Boemmels[EMAIL PROTECTED] Fachbereich Physik Tel: ++49-(0)631-205-2817 Universitaet Kaiserslautern Fax: ++49-(0)631-205-3906 PGP Key fingerprint = 9F 56 54 3D 45 C1 32 6F 23 F6 C7 2F 85 93 DD 47
Re: [RfC] constant PMCs and classes
Leopold Toetsch [EMAIL PROTECTED] writes: Benjamin Goldberg [EMAIL PROTECTED] wrote: #define PARROT_DECLARE_STATIC_STRING(name, cstring) \ [ big snip ] While Juergen's original or your proposal are fine, they don't work (or not as proposed). First there are compiler issues: $ gcc -Iinclude -Lblib/lib -lparrot -ldl -Wall -g bg.c ./a.out #v+ bg.c: In function `main': bg.c:35: warning: braces around scalar initializer bg.c:35: warning: (near initialization for `_Parrot_static_mystr_STRING.obj.u.int_val') bg.c:35: warning: initialization makes integer from pointer without a cast bg.c:35: warning: excess elements in scalar initializer bg.c:35: warning: (near initialization for `_Parrot_static_mystr_STRING.obj.u.int_val') #v- The first warning is about the Union initialisation. A initialiser of a union always initializes the first element, which is a INTVAL, but I wanted to initialize the last item (which is not possible in pure ANSI, but it turned out gcc got it right anyway). A simple change of order in the Union would make this warning go away. The declaration looks ok at first sight, my gcc 2.95.2 might be wrong, but anyway, a bigger problem is here: PIO_printf(interpreter, %S\n, mystr); Program received signal SIGSEGV, Segmentation fault. 0x400f8725 in make_COW_reference (interpreter=0x8049828, s=0x80486e0) at string.c:95 95 PObj_constant_CLEAR(s); (gdb) bac #0 0x400f8725 in make_COW_reference (interpreter=0x8049828, s=0x80486e0) at string.c:95 #1 0x400f91b6 in string_copy (interpreter=0x8049828, s=0x80486e0) at string.c:497 Ah it seems that make_COW_reference wants to change a constant string. As my code puts the static strings in .rodata (this was one of the targets of my experiments) it is not possible in any way to change this item. I even think PObj_constant_CLEAR(s) is evil. One reason for setting a PObj_constant_FLAG is to declare that an object will not change. Unsetting this flag means breaking this contract. snippet from objdump: .rodata0011 _Parrot_static_mystr_cstring.15 .rodata0024 _Parrot_static_mystr_STRING.16 If we get a general compiler independend solution for declaring static STRINGs we still have nothing for static keys. The main problem of all this code is the union initialiser. Static keys could also created with an initialisier, but i think this needs an other union-val to be initialized. There are gcc extension to init arbitary members, but ANSI-C allows only the initializiation of the first member. bye boe -- Juergen Boemmels[EMAIL PROTECTED] Fachbereich Physik Tel: ++49-(0)631-205-2817 Universitaet Kaiserslautern Fax: ++49-(0)631-205-3906 PGP Key fingerprint = 9F 56 54 3D 45 C1 32 6F 23 F6 C7 2F 85 93 DD 47
Re: [RfC] constant PMCs and classes
Leopold Toetsch [EMAIL PROTECTED] wrote: [ snip ] * const_string_from_cstring - return cached constant string or create one * const_key_new_cstring - return cached PMC or create a constant PMC Some more thoughts WRT this issue: - PerlHash isn't suitable for storing/lookup these STRINGs/Keys - so we would need a new hash type with a Cconst char* key (a simple implementation like the SymReg* hash inside symreg.c would suffice IMHO) - the keys shouldn't be copied into the hash, so they should be declared Cstatic const s[] = xxx (allocated in rodata). constant_key_new_cstring() is only needed because the hash interface is missing optimized a {s,g}et_type_keyed_str() interface. - the constant hash can be in the interpreter-iglobals array - implementation in a new Fconstants.c source file Comments welcome, leo PS: why we need it IMHO: $ find . -name '*.c' | xargs egrep '_cstring.*\w+' There are more, which are using string_make or multiple lines.
Re: [RfC] constant PMCs and classes
Juergen Boemmels wrote: Leopold Toetsch wrotes: We currently have constant Key and Sub PMCs both created from the packfile at load time. They live in the constant_table pointing to a constant PMC pool. But we need more. We have allover the core code like this: string_from_cstring(interpreter, pIt, 0) key = key_new_cstring(interpreter, _message); to create some STRINGs or entries in hashes. The keys should be constant PMCs and they should be shared as well as the STRINGs. We need this in objects.c (\0\0anonymous), for setting standard property names internally and for the current hash based implementation of Exceptions. [...] Some time ago I did some experiments with initialising strings at compile time. With some preprocessor magic and a perl program scanning the c-file I got it running. The changes to an existing c-file are minimal: At the beginning add a #include FILE.str and replace all these string_form_cstring with _S(text). The _S macros are replaced by static string_structures with static initialisers. These string structures are in the ro-data segement of the executable and should load really fast. No calls to any functions. I can think of a slightly easier method, one which would not depend on running a helper perl program. #define PCONCAT(b,c) _Parrot_static_##b##c #define PARROT_DECLARE_STATIC_STRING(name, cstring) \ static const char PCONCAT(name,_cstring) [] = cstring; \ static const struct parrot_string_t \ PCONCAT(name,_STRING) = { \ { /* pobj_t */ \ {{ \ (void*)PCONCAT(name,_cstring), \ sizeof(PCONCAT(name,_cstring)) \ }}, \ PObj_constant_FLAG \ GC_DEBUG_VERSION \ }, \ sizeof(PCONCAT(name,_cstring)), \ (void*)PCONCAT(name,_cstring), \ sizeof(PCONCAT(name,_cstring)) - 1, \ NULL, \ NULL, \ 0 \ }, * const name = PCONCAT(name,_STRING); [untested] Then, of course, one can simply declare the names and values of one's constant strings in any place where variables may be declared, using: PARROT_DECLARE_STATIC_STRING(mystr, some string here); Now, there's a const STRING * const mystr variable, whose contents are the some string here. Actually, I'm not sure that there's a need for the PCONCAT(name,_cstring) variable -- it might be possible to use cstring directly when initializing the struct. -- $a=24;split//,240513;s/\B/ = /for@@=qw(ac ab bc ba cb ca );{push(@b,$a),($a-=6)^=1 for 2..$a/6x--$|;print [EMAIL PROTECTED] ]\n;((6=($a-=6))?$a+=$_[$a%6]-$a%6:($a=pop @b))redo;}
Re: [RfC] constant PMCs and classes
Luke Palmer wrote: Ok, so supposing this split happens, what would it look like? As in, would there now be two vtables, one for variables and one for values? Would it just be a logical split? AFAIK we would have still one vtable divided into sub-structures. At least the get/set_type methods would be duplicated. For plain scalars the methods are the same, get_integer would directly return the int. For magic classes, one get_integer fetches the value and get_integer on the value returns the int. Thanks, Luke leo
Re: [RfC] constant PMCs and classes
Leopold Toetsch writes: Nicholas Clark [EMAIL PROTECTED] wrote: Could we split the vtable further, so var/value by read/write, which would allow constant objects to swap their write vtable to a throw implementation. Did I misread what you were suggesting either in this message or later, and you were suggesting this split? I'm suggesting exactly this split. Or lets say pmc2c.pl knows that e.g. [FETCH] is a read and [STORE] is a write, which will get a throw implementation for the Const$Class. WRT var/value split, I think only FETCH/STORE get duplicated in both sections. Ok, so supposing this split happens, what would it look like? As in, would there now be two vtables, one for variables and one for values? Would it just be a logical split? Thanks, Luke
Re: [RfC] constant PMCs and classes
[ The listserver does not like my attachments ezmlm-send: fatal: Sorry, after removing unacceptable MIME parts from your message I was left with nothing (#5.7.0) ezmlm-gate: fatal: fatal error from child Here is the resend with code inline ] Leopold Toetsch [EMAIL PROTECTED] writes: We currently have constant Key and Sub PMCs both created from the packfile at load time. They live in the constant_table pointing to a constant PMC pool. But we need more. We have allover the core code like this: string_from_cstring(interpreter, pIt, 0) key = key_new_cstring(interpreter, _message); to create some STRINGs or entries in hashes. The keys should be constant PMCs and they should be shared as well as the STRINGs. We need this in objects.c (\0\0anonymous), for setting standard property names internally and for the current hash based implementation of Exceptions. [...] Some time ago I did some experiments with initialising strings at compile time. With some preprocessor magic and a perl program scanning the c-file I got it running. The changes to an existing c-file are minimal: At the beginning add a #include FILE.str and replace all these string_form_cstring with _S(text). The _S macros are replaced by static string_structures with static initialisers. These string structures are in the ro-data segement of the executable and should load really fast. No calls to any functions. = c2str.pl #! perl use Text::Balanced qw(extract_bracketed); use Data::Dumper; die $0: Usage $0 FILE.c unless $#ARGV == 0; my $file = shift @ARGV; $file =~ s/\.c$//; my $infile = $file . '.c'; my $outfile = $file . '.str'; die $0: $infile: $! unless -e $infile; print 'HEADER'; /* * !!! DO NOT EDIT THIS FILE !!! * * This file is generated automatically from '$infile' * by $0. * * Any changes made here will be lost! * */ #define CONCAT(a,b) a##b #define _S(name) (__PARROT_STATIC_STR(__LINE__)) #define __PARROT_STATIC_STR(line) CONCAT(static_string_, line) #include parrot/pobj.h #if ! DISABLE_GC_DEBUG # define GC_DEBUG_VERSION ,0 #else # define GC_DEBUG_VERSION #endif HEADER my %known_strings = (); sub output_string { my ($text, $line) = @_; if (exists $known_strings{$text}) { DATA; #define static_string_${line} static_string_$known_strings{$text} DATA } else { $known_strings{$text} = $line; DATA; static const char static_string_${line}_data\[\] = $text; static const struct parrot_string_t static_string_${line} = { { /* pobj_t */ {{ (void*)static_string_${line}_data, sizeof(static_string_${line}_data) }}, PObj_constant_FLAG GC_DEBUG_VERSION }, sizeof(static_string_${line}_data), (void*)static_string_${line}_data, sizeof(static_string_${line}_data) - 1, NULL, NULL, 0 }; DATA } } open IN, $infile; my $line = 0; while (IN) { $line++; next if m/^\s*\#/; # ignore preprocessor next unless s/.*\b_S\b//; my $str = extract_bracketed $_, '()'; print output_string (substr($str,1,-1), $line); } = example.c /* * example.c * * demonstrating static allocation of string * * to compile: * perl c2str.pl example.c example.str * gcc -o example -Iinclude example.c blib/lib/libparrot.a -lm -ldl */ #include parrot/parrot.h #include example.str int main(int argc, char* argv[]) { struct Parrot_Interp * interpreter; interpreter = Parrot_new(); Parrot_init(interpreter, interpreter); PIO_putps(interpreter, PIO_STDOUT(interpreter), _S(foo\n)); PIO_putps(interpreter, PIO_STDOUT(interpreter), _S(bar\n)); PIO_putps(interpreter, PIO_STDOUT(interpreter), _S(foo\n)); return 0; } = Issues with this are: * My macro vodoo is base on __LINE__ so only one _S directive per line * the strings are local to one compilation unit (but that is not diffrent from the c-string constants) * It exposes the internal structure of PObj (this does not bother us at the moment, nearly every file includes parrot/parrot.h) * The encoding/chartype must be set to 0 or we get a many relocations, the string functions have to deal with this case. May a scheme like this can be used for keys too. Comments welcome leo Same here boe -- Juergen Boemmels[EMAIL PROTECTED] Fachbereich Physik Tel: ++49-(0)631-205-2817 Universitaet Kaiserslautern Fax: ++49-(0)631-205-3906 PGP Key fingerprint = 9F 56 54 3D 45 C1 32 6F 23 F6 C7 2F 85 93 DD 47
Re: [RfC] constant PMCs and classes
On Wed, Aug 20, 2003 at 02:05:19PM +0200, Leopold Toetsch wrote: This leads to changes in parsing the vtable.tbl - which we need anyway to do the proposed var/value split of vtables. e.g. [FETCH] get_integer ... [STORE] set_integer ... [PUSH] push_integer ... and so on. The section names conform (where applicable) to methods described in Tie::*(3pm). Comments welcome It's been noted that FETCHSLICE/STORESLICE are missing from the perl5 tied hash API, but that adding them at this stage would cause subtle bugs: http://www.xray.mpe.mpg.de/mailing-lists/perl5-porters/2001-11/msg02044.html Could we split the vtable further, so var/value by read/write, which would allow constant objects to swap their write vtable to a throw implementation. Did I misread what you were suggesting either in this message or later, and you were suggesting this split? I'm not sure if a simple read/write split also helps PMCs shared across threads. Maybe sharing between threads is a whole new can of worms that we should leave untouched for now. Nicholas Clark
Re: [RfC] constant PMCs and classes
Nicholas Clark [EMAIL PROTECTED] wrote: On Wed, Aug 20, 2003 at 02:05:19PM +0200, Leopold Toetsch wrote: This leads to changes in parsing the vtable.tbl - which we need anyway to do the proposed var/value split of vtables. e.g. [FETCH] get_integer ... [STORE] set_integer ... [PUSH] push_integer ... and so on. The section names conform (where applicable) to methods described in Tie::*(3pm). Comments welcome Could we split the vtable further, so var/value by read/write, which would allow constant objects to swap their write vtable to a throw implementation. Did I misread what you were suggesting either in this message or later, and you were suggesting this split? I'm suggesting exactly this split. Or lets say pmc2c.pl knows that e.g. [FETCH] is a read and [STORE] is a write, which will get a throw implementation for the Const$Class. WRT var/value split, I think only FETCH/STORE get duplicated in both sections. I'm not sure if a simple read/write split also helps PMCs shared across threads. Maybe sharing between threads is a whole new can of worms that we should leave untouched for now. When a PMC is shared it is either ro or rw - in all threads. I don't see a problem here. Nicholas Clark leo
Re: [RfC] constant PMCs and classes
On Thu, Aug 21, 2003 at 03:31:42PM +0200, Leopold Toetsch wrote: Nicholas Clark [EMAIL PROTECTED] wrote: I'm not sure if a simple read/write split also helps PMCs shared across threads. Maybe sharing between threads is a whole new can of worms that we should leave untouched for now. When a PMC is shared it is either ro or rw - in all threads. I don't see a problem here. I don't see a problem but I do see a possible optimisation. I can't remember if you were still in the p5p meeting in Paris when Arthur explained Sarathy/his idea about doing copy on write of whole scalars in perl5 for ithreads. Basically the idea was that when a new thread is created, scalars aren't copied immediately. However, they aren't locked - they are treated as read only (with a reference count, boo hiss, of interested threads) If a thread finds that it needs to modify something (with a reference count = 2) then it does lock that scalar (and checks again) At that point it makes its own copy of the scalar, leaving the original intact (untouched) for the other threads to keep on seeing. (Obviously when it has made the copy it then unlocks the other) The last thread inherits the original. The beauty is that no shared scalar is ever written. I think that something like this could also work in parrot - you replace the write vtable ops with the lock/check/copy versions, but leave the read ops intact. When you do the copy and it's now an unshared PMC you revert the write vtable ops to the usual fast set. Hence why I made a connection between split read/write ops and threading. Nicholas Clark
Re: [RfC] constant PMCs and classes
Nicholas Clark [EMAIL PROTECTED] wrote: On Thu, Aug 21, 2003 at 03:31:42PM +0200, Leopold Toetsch wrote: When a PMC is shared it is either ro or rw - in all threads. I don't see a problem here. I don't see a problem but I do see a possible optimisation. I can't remember if you were still in the p5p meeting in Paris when Arthur explained Sarathy/his idea about doing copy on write of whole scalars in perl5 for ithreads. A yes that. I wasn't on my first beer at this time but I remember it. I didn't fully understand the implications of this proposal, but with ... [ snip ] The beauty is that no shared scalar is ever written. I think that something like this could also work in parrot - you replace the write vtable ops with the lock/check/copy versions, but leave the read ops intact. When you do the copy and it's now an unshared PMC you revert the write vtable ops to the usual fast set. ... this excellent (thanks) explanation, this seems to be very promising and doable, because ... ... Hence why I made a connection between split read/write ops and threading. ... a Const$PMC has a different vtable then $PMC. A Shared$Something has the set-like part of its vtable changed, so its yet another PMC type. When there is a need to copy the PMC, because it would be written to, the orginal vtable (being the Const one or not) has to be swapped in, and that's it. So basically, we just have to remember the original vtable* (or class enum) in the changed vtable, to restore the previous one. Then the vtable method gets redone, for the shared case it finally would throw an exception if the PMC was ro (and we could again set the shared vtable here) Albeit, we might end up with a non trivial amount of combinations of vtables consisting of permutations of different vtable pieces ... Nicholas Clark leo
[RfC] constant PMCs and classes
We currently have constant Key and Sub PMCs both created from the packfile at load time. They live in the constant_table pointing to a constant PMC pool. But we need more. We have allover the core code like this: string_from_cstring(interpreter, pIt, 0) key = key_new_cstring(interpreter, _message); to create some STRINGs or entries in hashes. The keys should be constant PMCs and they should be shared as well as the STRINGs. We need this in objects.c (\0\0anonymous), for setting standard property names internally and for the current hash based implementation of Exceptions. This leads to my proposal: * const_string_from_cstring - return cached constant string or create one * const_key_new_cstring - return cached PMC or create a constant PMC * constant_pmc_new* - ditto (called from above) Further we would need for some classes a Const$Class variant, where the set-like vtables throw an exception. These classes should be autogenerated from *.pmc for all classes that have a const_too or such in their classes $flags. This leads to changes in parsing the vtable.tbl - which we need anyway to do the proposed var/value split of vtables. e.g. [FETCH] get_integer ... [STORE] set_integer ... [PUSH] push_integer ... and so on. The section names conform (where applicable) to methods described in Tie::*(3pm). Comments welcome leo
RE: [RfC] constant PMCs and classes
Leopold Toetsch: # Further we would need for some classes a Const$Class variant, where the # set-like vtables throw an exception. These classes should be # autogenerated from *.pmc for all classes that have a const_too or such # in their classes $flags. Isn't The Plan(tm) to use properties for this? --Brent Dax [EMAIL PROTECTED] Perl and Parrot hacker Yeah, and my underwear is flame-retardant--that doesn't mean I'm gonna set myself on fire to prove it.
Re: [RfC] constant PMCs and classes
Brent Dax wrote: Leopold Toetsch: # The property 'constant', 'ro' or whatever can only be some kind of # communication: the HLL is telling the PMC to be read only. We could now # have in each set-like vtable: # #if (we_have_props !is_bool(prop(ro)) // pseudo code # set_the_value ... #else # throw_exception # #or we have a different class, that have in the set-like vtable slots # just the exception. No penalty for rw classes. I'm starting to wonder if we shouldn't copy the vtable at construction time. That way, we can have our read-only set_* behaviors without requiring a second class: void init(...) { SELF-vtable=copy(this_class's_vtable); if(is_bool(prop(ro)) { SELF-vtable-set_int=Parrot_pmc_ro_set_int; This would work for properties known at constrution time. But it doesn't much help, if at runtime the ro property is set. This scheme would work e.g. for tie, where a new variable (ref) is returned, with different vtable pieces allocated and copied in. Allocating new vtables at runtime for the same object instance would need some book-keeping (vtable already allocated, which entries...). And the more that constant objects are used internally, I think its better to create these at compile time. This would also allow for other class-specific vtable customization. After all, I doubt ro will be the *only* property that's much more efficiently implemented as a modified vtable... Yep. That's right, your scheme matches somehow my tied sample code, I posted long times ago. A generalization of my compile time classes variations for runtime modifications is for sure necessary - somewhen. But for now (and as long Dan's specs for vtable chenges are hidden) I don't want to go further. leo
RE: [RfC] constant PMCs and classes
Leopold Toetsch: # The property 'constant', 'ro' or whatever can only be some kind of # communication: the HLL is telling the PMC to be read only. We could now # have in each set-like vtable: # #if (we_have_props !is_bool(prop(ro)) // pseudo code # set_the_value ... #else # throw_exception # #or we have a different class, that have in the set-like vtable slots # just the exception. No penalty for rw classes. I'm starting to wonder if we shouldn't copy the vtable at construction time. That way, we can have our read-only set_* behaviors without requiring a second class: void init(...) { SELF-vtable=copy(this_class's_vtable); if(is_bool(prop(ro)) { /* * I see no reason we can't provide one implementation * for all read-onlys--after all, it just needs to throw * an exception. */ SELF-vtable-set_int=Parrot_pmc_ro_set_int; SELF-vtable-set_num=Parrot_pmc_ro_set_num; SELF-vtable-set_string=Parrot_pmc_ro_set_string; SELF-vtable-set_pmc=Parrot_pmc_ro_set_pmc; ... } } This would also allow for other class-specific vtable customization. After all, I doubt ro will be the *only* property that's much more efficiently implemented as a modified vtable... --Brent Dax [EMAIL PROTECTED] Perl and Parrot hacker Yeah, and my underwear is flame-retardant--that doesn't mean I'm gonna set myself on fire to prove it.