Account Options

  1. Sign in
The old Google Groups will be going away soon, but your browser is incompatible with the new version.
Google Groups Home
« Groups Home
Message from discussion Transferring control between code segments, eval, and suchlike things

Newsgroups: perl.perl6.internals
Path: archiver1.google.com!news1.google.com!newsfeed.stanford.edu!nntp.perl.org
Return-Path: <d...@sidhe.org>
Mailing-List: contact perl6-internals-h...@perl.org; run by ezmlm
Delivered-To: mailing list perl6-intern...@perl.org
Mime-Version: 1.0
X-Sender: d...@redcap.sidhe.org (Unverified)
Message-ID: <a05200f02ba5497181516@[192.168.2.1]>
Date: Wed, 22 Jan 2003 15:00:37 -0500
To: perl6-intern...@perl.org
Subject: Transferring control between code segments, eval, and suchlike things
Content-Type: text/plain; charset="us-ascii" ; format="flowed"
X-SMTPD: qpsmtpd/0.20, http://develooper.com/code/qpsmtpd/
Approved: n...@nntp.perl.org
From: d...@sidhe.org (Dan Sugalski)
Lines: 101

Okay, since this has all come up, here's the scoop from a design perspective.

First, the branch opcodes (branch, bsr, and the conditionals) are all 
meant for movement within a segment of bytecode. They are *not* 
supposed to leave a segment. To do so was arguably a bad idea, now 
it's officially an error. If you need to do so, branch to an op that 
can transfer across boundaries.

Design Edict #1: Branches, which is any transfer of control that 
takes an offset, may *not* escape the current bytecode segment.

Next, jumps. Jumps take absolute addresses, so either need fixup at 
load time (blech), are only valid in dynamically generated code 
(okay, but limiting), or can only jump to values in registers (that's 
fine). Jumps aren't a problem in general.

Design Edict #2: Jumps may go anywhere.

Destinations. These are a pain, since if we can go anywhere then the 
JIT has to do all sorts of nasty and unpleasant things to compensate, 
and to make every op a valid destination. Yuck.

Design Edict #3: All destinations *must* be marked as such in the 
bytecode metadata segment. (I am officially nervous about this, as I 
can see a number of ways to subvert this for evil)

I'm only keeping jumps (and their corresponding jsr) around for 
nostalgic reasons, and with the vague hope they may be useful. I'm 
not sure about this.

Design Edict #4: Dan is officially iffy on jumps, but can see them as 
useful for lower-level statically bound languages such as forth, 
Scheme, or C.

That leads us to

Design Edict #5: Dan will accommodate semantics for languages outside 
the core set (perl, python, ruby) only if they don't compromise 
performance for the core set.

Calling actual routines--subs, methods, functions, whatever--at the 
high level isn't done with branches or jumps. It is, instead, done 
with the call series of ops. (call, callmeth, callcc, tailcall, 
tailcallmeth, tailcallcc (though that one makes my head hurt), 
invoke) These are specifically for calling code that's potentially in 
other segments, and to call into them at fixed points. I think these 
need to be hashed out a bit to make them more JIT-friendly, but 
they're the primary transfer destination point

Design Edict #6: The first op in a sub is always a valid 
jump/branch/control transfer destination

Now. Eval. The compile opcode going in is phenomenally cool (thanks, 
Leo!) but has pointed out some holes in the semantics. I got 
handwavey and, well, it shows. No cookie for me.

The compreg op should compile the passed code in the language that is 
indicated and should load that bytecode into the current interpreter. 
That means that if there are any symbols that get installed because 
someone's defined a sub then, well, they should get installed into 
the interpreter's symbol tables.

Compiled code is an interesting thing. In some cases it should return 
a sub PMC, in some cases it should execute and return a value, and in 
some cases  it should install a bunch of stuff in a symbol table and 
then return a value. These correspond to:


    eval "print 12";

    $foo = eval "sub bar{return 1;}";

    require foo.pm;

respectively. It's sort of a mixed bag, and unfortunately we can't 
count on the code doing the compilation to properly handle the 
semantics of the language being compiled. So...

Design Edict #7: the compreg opcode will execute the compiled code, 
calling in with parrot's calling conventions. If it should return 
something, then it had darned well better build it and return it.

Oh, and:

Design Edict #8: compreg is prototyped. It takes a single string and 
must return a single PMC. The compiler may cheat as need be. (No need 
to check and see if it returned a string, or an int)

Yes, this does mean that for plain assembly that we want to compile 
and return a sub ref for we need to do extra in the assembly we pass 
in. Tough, we can deal. If it was dead-simple it wouldn't be 
assembly. :)

I think that's it. Let's have at it and see where the edicts need fixing.
-- 
                                         Dan

--------------------------------------"it's like this"-------------------
Dan Sugalski                          even samurai
d...@sidhe.org                         have teddy bears and even
                                       teddy bears get drunk