.global int foo = 42
.global pmc bar
.sub init :immediate
bar = new .FixedIntegerArray
bar = 4
.end
> Supporting C static storage
>
> There are some related Perl6 features, namely INIT and FIRST closure
> traits [1], which aren't really covered by Parrot yet.
>
> Parrot supports INIT blocks via :immediate, which allows e.g.
> translation of:
>
> constant Num pi = { atan(1,1)*4 }; # [2]
>
> But C statics can of course change. The problems is, where to
> store the static variable, especially native integers.
>
> double gen_random(double max) { # [3]
> static long last = 42;
> ...
> }
>
> We could use closures, coroutines [4], or globals. The former provide
> a persistent register frame, where the static can be kept. Translating
> a sub with a C static to a coroutine seems to be a bit unnatural
> though. And all these solutions are a bit slow and lexicals/globals
> are only providing PMC support.
>
> I think, we should use the constant table and allow storing into
> the constant table.
>
> E.g.
>
> .static int last = 42 # ldc_i_ic
>
> (We can't use the C<set_i_ic> opcode, as this is loading constants
> from the bytecode, which, when mmaped, is readonly and doesn't allow
> storing)
>
> last += 10 # add_i_ic / set_ic_i
>
> .static float f = 3.14 # set_n_nc
> f += 2.0 # add_n_nc / set_nc_n
> f = 5.0 # set_n_nc / set_nc_n
>
> .static .Integer i = "42" # set_p_pc
>
> The 'static' variables are therefore working mostly like constants,
> except that they are modifyable. One difference is of course, that
> there would be no constant folding, each .static needs a distinct
> storage in the constant table.
>
> We'd need a few new opcodes:
>
> ldc_i_ic # load int constant from constant table
> set_ic_i # store int into constant table
> set_nc_n # store num
> assign_pc_p # assign to PMC static value
>
> And maybe some permutations like set_pc_i.
>
> What do you think?
> leo
>
>
> [1] S04 / Closure traits
>
> [2] # t/pmc/sub_38.pir
> .sub make_pi :immediate, :anon
> $N0 = atan 1.0, 1.0
> $N0 *= 4
> $P0 = new .Float
> $P0 = $N0
> .return ($P0)
> .end
>
> .sub main :main
> .const .Sub pi = "make_pi"
> print pi
> print "\n"
> .end
>
> [3]
> http://shootout.alioth.debian.org/sandbox/benchmark.php?
> test=random&lang=icc&id=0
>
> [4] examples/shootout/random.pir
> I think, we should use the constant table and allow storing into
> the constant table.
I don't know the parrot source code well enough to know whether the constant
table is static const at the C level. (Or capable of being compiled that way).
But my comment is that Jarkko recently put considerable effort into cleaning
up the Perl 5 core so that as much data as possible was static const, so that
it facilitated shared library use. (In this case for Symbian)
So I (mis)interpret "storing to the constant table" as "aaargh, can't be static
const" which feels bad to me. So if the constant table can be static const,
does this mean that parrot would benefit from a compile time initialised
constant table, and a "run time" initialised constant table? With your
proposed writable C static variables in the run time initialised table.
Nicholas Clark
> On Mon, Jan 30, 2006 at 03:54:51PM +0100, Leopold Toetsch wrote:
>
>> I think, we should use the constant table and allow storing into
>> the constant table.
>
> I don't know the parrot source code well enough to know whether the
> constant
> table is static const at the C level. (Or capable of being compiled
> that way).
No it's not a C static const and it can't be considered a such. It's
built at compile/PBC load time incrementally by appending e.g. doubles
or PMC constants, like subroutine PMC, or STRING constants. A C static
const alike is e.g. used for STRING constants in the source code, via
the CONST_STRING macro.
> But my comment is that Jarkko recently put considerable effort into
> cleaning
> up the Perl 5 core so that as much data as possible was static const,
> so that
> it facilitated shared library use. (In this case for Symbian)
Good point, albeit it doesn't apply to the thing currently called
constant table.
> So I (mis)interpret "storing to the constant table" as "aaargh, can't
> be static
> const" which feels bad to me. So if the constant table can be static
> const,
> does this mean that parrot would benefit from a compile time
> initialised
> constant table, and a "run time" initialised constant table? With your
> proposed writable C static variables in the run time initialised table.
The constant table is currently a list of pointers to unions of
'constant' values. It's created when loading a bytecode file (or
equivalently during compile/run cycle). *If* the the constant table
were split into more dedicated parts, a const list of doubles could be
part of the PBC and be considered as read-only/shared because it would
be just mmaped, if possible.
The 'constant' part of the table means for Parrot internals that it
isn't marked being alive by the GC, because these items (STRINGs, PMCs)
in the constant table have a dedicated storage arena, which is only
freed at program end (and possibly with --leak-test enabled).
> Nicholas Clark
leo
> But C statics can of course change. The problems is, where to
> store the static variable, especially native integers.
Another idea:
We keep the call frame of subs with statics (or Perl6 INIT and FIRST
blocks) after returning from the sub. Additionally, we can set a new
entrypoint for the sub after running the INIT code (or static
initializer). The entrypoint would be reset for cloning closures to
achieve perl6 FIRST block semantics.
The draw backs are increased memory usage and it doesn't work together
with recursive subroutines easily, albeit I don't know, if recursive
subs with statics are really meaningful.
E.g.
.sub "gen_random"
.param float max
.static int last # just an alias for .local maybe
last = 42
after_init gen_random_init_done # move sub entry point
goto gen_rand_2 # after_init could branch too
gen_random_init_done: # automatically
.param float max # duplicated get_params
gen_rand_2
....
.end
Comments welcome,
leo
Uh, maybe I'm pointing out something that's already blindingly obvious
to everyone else, but for "state" variables cloned closures can't
use the same static storage location. (Or is that what you're meaning
already by "keep the call frame"?)
: The draw backs are increased memory usage and it doesn't work together
: with recursive subroutines easily, albeit I don't know, if recursive
: subs with statics are really meaningful.
Unlike the situation with clones, a "state" variable *is* shared
between recursive invocations. As for whether that's meaningful,
I don't know either. But you could, say, temporize such a variable
just like a global, and that might make some kind of sense. Anyway,
the P6 model of "state" is more like a persistent lexical than like
C's static. (Though of course Parrot will probably want C's static
semantics for various other languages...)
Anyway, I thought I'd clarify a bit--we just don't want people
confusing "state" with "static", given the similarity of the names.
Larry
Yep. With the scheme mentioned above a cloned closure would get a fresh
'state' variable as it of course needs distinct registers (aka call
frame) too.
> : The draw backs are increased memory usage and it doesn't work together
> : with recursive subroutines easily, albeit I don't know, if recursive
> : subs with statics are really meaningful.
>
> Unlike the situation with clones, a "state" variable *is* shared
> between recursive invocations. As for whether that's meaningful,
> I don't know either.
That's the same with a C static. Rescursion (not tail recursion) would
need some extra copying of state vars and book-keeping of register frames.
> ...But you could, say, temporize such a variable
> just like a global, and that might make some kind of sense.
Yep.
> ... Anyway,
> the P6 model of "state" is more like a persistent lexical than like
> C's static.
Sorry for my dumb question - what's the difference then? (Besides that C
dosn't have closures ;)
> ... (Though of course Parrot will probably want C's static
> semantics for various other languages...)
>
> Anyway, I thought I'd clarify a bit--we just don't want people
> confusing "state" with "static", given the similarity of the names.
>
> Larry
leo
That *is* the difference. But for those of us handicapped by coming
from a C background, the extension of "static" semantics into closure
space would tend to lead one toward thinking that all clones share a
particular state variable, because a C programmer doesn't really known
when he's confusing a particular storage mechanism with a particular
semantic model. But then, all humans tend to confuse cultural truth
with universal truth--even when (some would say "especially when")
they come from a culture that aspires to learn universal truth.
Hmm, I'm not sure I've ever slammed fundamentalists and mathematicians
in the same sentence before... :-)
Larry