Re: pbr vs multiple returns

new topic     » goto parent     » topic index » view thread      » older message » newer message

Pete Lomax wrote:
> 
> cchris005 wrote:
> > 
> > > Subject: Re: Digest for EUforum at topica.com, issue 6333
> > > 
> > > 
> > > posted by: Pete Lomax <petelomax at blueyonder.co.uk>
> > > 
> > > CChris wrote:
> > > > }}}
<eucode>
> > > > function pop(byref sequence stack)
> > > > object top
> > > > top=stack[$]
> > > > stack=stack[1..$-1]
> > > > return top
> > > > end function
> > > > </eucode>
{{{

> > > 
> > > > Currently, you need to return both the modified stack and the former top
> > > >
> > > > element, which is awkward.
> > > 
> > > FWIW, I plan something like:
> > > }}}
<eucode>
> > > function[2] pop(sequence stack)
> > >     return stack[$], stack[1..$-1]
> > > end function
> > > 
> > > {nextitem,stack}=pop(stack)
> > > </eucode>
{{{

> > > 
> > > > More generally, PBR enables to transform an object, rather to return a 
> > > > modified object which you have to copy onto the original - waste of CPU.
> > > Technically, I plan an "unnecessary" dword move which "true" pbr
> > > wouldn't; but that is trivial overhead compared to existing cow semantics
> > > (in fact so trivial I very much doubt it would ever show on any timing
> > > test).
> > > 
> > 
> > Would that "dword move" also work when transforming a subscripted
> > quantity, like (3]?
> Hopefully, I'll know more when I start implementing it, see below.
> 
> > 
> > And, by the way, would you really expect to get the modified stack in
> > the returned value? I probably programmed too much in asm, but I find
> > this a bit confusing. And you have to perform an extra s1=s[1] to get
> > the value you need.
> You seem to be confusing
> }}}
<eucode>
>     return stack[$],stack[1..$-1]
> </eucode>
{{{

> with
> }}}
<eucode>
>     return {stack[$],stack[1..$-1]}
> </eucode>
{{{

> 
> So, no, I don't expect to get the modified stack "in" "the" return value,
> I expect to get the modified stack as the second return value.
> 

All right. But I would have used multiple return for other stuff rather. 
I fully understand why Jason is confused.

> Internally, I plan to implement eg:
> }}}
<eucode>
> function[2] pop(sequence stack)
>    return stack[$], stack[1..$-1]
> end function
> 
> {nextitem,stack}=pop(stack)
> </eucode>
{{{

> as something similar to (pseudocode):
> }}}
<eucode>
> object fres1,fres2  -- virtual, of course
> sequence popstack   -- scoped to pop, ""
> pop:
>     fres1=popstack[$]
>     fres2=popstack[1..$-1]
> ret
> 
> popstack=stack
> stack=<no value>
> call pop
> top=fres1
> stack=fres2
> </eucode>
{{{

> When I said "mov dword" I was referring to the last two statements, a neglible
> and insignificant cost for avoiding cow overheads.
> 
> Going back to a[i]=update(a[i]), I expect that to be frighteningly difficult
> to fully optimise with this multiple returns approach and may need real pbr.
> 

So why confuse the matter by taking multiple return in, since they would be a 
partial solution to the problem at best?
If you see the same IL code repeated in the way you'd have with 
s[i]=update(s[i]), it doesn't look frigteningly difficult to replace the 
part that repeats left_sym with left_sym itself. Not trivial (you have to 
keep track of which sequence of IL translates which assignable or expression), 
but not awful I'd think.


> But anyway, I think multiple returns are a pretty neat feature in their own
> right, albeit not quite as flexible as true pbr.
> 
> > Your proposal doesn't look very good to me.
> Maybe not. Let me just add that it seems Rob has gone to great lengths to
> optimise
> say x=append(x,...) and I feel that optimisation should be generalised so it
> applies to user code, not just a handful of builtins.
> 
> > 
> > > > Eu has function pointers, using call_back(routine_id(rt_name)). What 
> > > > confuses me is why I can't do it with variables. Am I the only one?
> > > 
> > > Firstly, as background, a routine_id is *utterly meaningless* to any
> > > other than call_func, call_proc, and call_back. Agreed?
> > > 
> > 
> > True. What is the issue?
> I think I was trying to say that you'd never pass a routine_id to a c func,
> unless you intend to have it passed back to Eu code, as C code cannot do
> anything
> with it. Likewise variable_id would be no use to C code. I was just trying to
> set the scene and make it clear I was not talking about var_id but
> raw_address(var_id).
> 

Oh I see. And I didn't get that point because I wasn' talking yet about 
raw_pointer().

> > Did you ever try to allow an external dll/piece of code to access an Eu
> > variable? And do you think this is not right?
> I've always used raw blocks of memory when dealing with C code.
> 
> > Using a get_this_var()/set_this_var(typeof_this_var x) pair for every
> > such variable looks really like a bad idea to me. That's how we wind up
> > doing it unfortunately.
> Well it seems to me that call_back(get_var) and call_back(set_var) would be
> the only way you could possibly manipulate Eu vars from C code. Very tricky
> but at least possible. See below.
> > 
> > Admittedly, you an also alloocate an address (isn't this a raw pointer?)
> Yes but it is not an Eu variable.
> > and use this for interfacing. Only problem is that peek/poke are so darn
> > slow...
> Separate issue.

No. If it were reasonably fast (not more than 5-6 tests and mov's), then 
there would be no need for a more efficient way to hand raw pointers to 
external code. And you'd have no need for raw_pointer() altogether.

> > 
> > But indeed, my primary point was: there's a routine_id, why is a
> > variable_id() any more complicated? Hence why is it not implemented?
> It is a shed load more complicated.
> You don't modify routines.
> They don't move about.
> If you do x=append(x,x) then almost always x will have been shifted somewhere
> else in memory.

I was referring to handles in my previous posts. var_id would be a purely 
Eu handle to a roaming memory location. Must be "volatile" as your example 
shows, ie be evaluated every tilme it is invoked. routine_id's are 
_identical_: the only difference is that they are not volatile - they don't 
move.

> 
> Consider string s="text".
> In assembly this goes something like:
>   dd 4  ; length
>   dd 0x82000001 ; type and refcount
> data db "text",0
> align 4
> 
> s dd (data+1) ror 2
> (see execute.h for Eu implementation, which shifts 3 and uses different high
> bits, etc)
> 
> So, say we get the actual address of s and pass it to a C function. Is it
> goiing
> to know what to do with it? Does it understand the types? Will it honour the
> refcounts and clone things when needed? Will it maintain length (and base and
> postfill)? When the C code craps on things, is the Eu backend going to
> cope/give
> intelligible error messages? Will it promise not to make circular references?
> Will it typecheck things it modifies? And so on.
> 

Wait. If you open accass to a dword or *float, nothing of this happens.

> Open this up and you completely destabalise the backend.
> 
> If you get to a point in some C code where you want to modify some Eu vars,
> you are far better off invoking a call_back and doing it in Eu, imo.
> The same is probably true if you just want to subscript an Eu var in C.
> 

C doesn't know about sequences, only homogeneous arrays. Hence, you won't 
be passing an Eu sequence to a C routine, except if it is a sequence of 
integers or floats. The logical thing to do then would be to poke the sequence
in memory getting an array of machine/C type, pass that to externa;l code and 
then peek back. Problem is, we usually want to do this to take advantage of 
raw speed in external code, but the overhead of the back and forth copy 
process offsets the benefits.

To sum up that multi-topic thread:
* multiple returns are nice and desirable;
* they don't substitute for PBR, which is also desirable;
* faster peek/poke is probably a goal to achieve; it's so fast in asm;
* var_id() returns a handle to be used only by get_var(), set_var(),
get_var_type(), is_initialised() and friends. Raw var_id's are as useless 
to external code as raw routine_id's.
* An equivalent of call_back() for variables would be far trickier than 
call_back(), and hardly needed if peek/poke worked as efficiently as one 
would expect.

Further comments may have to go to separate threads perhaps.

Regards.
CChris

> Regards,
> Pete

new topic     » goto parent     » topic index » view thread      » older message » newer message

Search



Quick Links

User menu

Not signed in.

Misc Menu